);
}
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 2b13b80a7..447e6bc8e 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -1459,9 +1459,6 @@
position: relative;
width: 100%;
height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
img {
max-width: $media-modal-media-max-width;
diff --git a/package.json b/package.json
index 76f665dba..dfba49afc 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
"file-loader": "^0.11.2",
"font-awesome": "^4.7.0",
"glob": "^7.1.1",
+ "hammerjs": "^2.0.8",
"http-link-header": "^0.8.0",
"immutable": "^3.8.2",
"imports-loader": "^0.8.0",
diff --git a/yarn.lock b/yarn.lock
index a1dd4c694..a306ebf55 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3092,6 +3092,10 @@ gzip-size@^3.0.0:
dependencies:
duplexer "^0.1.1"
+hammerjs@^2.0.8:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1"
+
handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
From 9ed5eebd7ce8381af77dd2918678202a0776af4a Mon Sep 17 00:00:00 2001
From: ThibG
Date: Thu, 29 Mar 2018 00:52:24 +0200
Subject: [PATCH 009/442] Do not ignore unknown media attachments, only skip
them (#6948)
That way, they are displayed in a list below the corresponding toot.
---
app/lib/activitypub/activity/create.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 676e885c0..afee8a268 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -113,13 +113,13 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
media_attachments = []
as_array(@object['attachment']).each do |attachment|
- next if unsupported_media_type?(attachment['mediaType']) || attachment['url'].blank?
+ next if attachment['url'].blank?
href = Addressable::URI.parse(attachment['url']).normalize.to_s
media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['name'].presence, focus: attachment['focalPoint'])
media_attachments << media_attachment
- next if skip_download?
+ next if unsupported_media_type?(attachment['mediaType']) || skip_download?
media_attachment.file_remote_url = href
media_attachment.save
From 41452e83028148b3ef6e5888e9bd3b16fd608ec7 Mon Sep 17 00:00:00 2001
From: unarist
Date: Thu, 29 Mar 2018 19:59:12 +0900
Subject: [PATCH 010/442] Fix TypeError on follow notification (#6950)
`notification.status` may not be present, e.g. follow notification.
---
app/javascript/mastodon/actions/notifications.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 7267b85bd..da77afbe0 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -43,7 +43,9 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
const playSound = getState().getIn(['settings', 'notifications', 'sounds', notification.type], true);
dispatch(importFetchedAccount(notification.account));
- dispatch(importFetchedStatus(notification.status));
+ if (notification.status) {
+ dispatch(importFetchedStatus(notification.status));
+ }
dispatch({
type: NOTIFICATIONS_UPDATE,
From f1f846045f26518525d5484ed9e782b73086ebe4 Mon Sep 17 00:00:00 2001
From: unarist
Date: Thu, 29 Mar 2018 21:57:02 +0900
Subject: [PATCH 011/442] Fix ReferenceError when Cache API is missing (#6953)
Cache API is not supported on Safari 11.0 / iOS 11.
Since those caching is optional, this patch simply ignores it.
---
app/javascript/mastodon/storage/modifier.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/javascript/mastodon/storage/modifier.js b/app/javascript/mastodon/storage/modifier.js
index 63e49fe6e..1bec04d0f 100644
--- a/app/javascript/mastodon/storage/modifier.js
+++ b/app/javascript/mastodon/storage/modifier.js
@@ -4,7 +4,10 @@ import { autoPlayGif } from '../initial_state';
const accountAssetKeys = ['avatar', 'avatar_static', 'header', 'header_static'];
const avatarKey = autoPlayGif ? 'avatar' : 'avatar_static';
const limit = 1024;
-const asyncCache = caches.open('mastodon-system');
+
+// ServiceWorker and Cache API is not available on iOS 11
+// https://webkit.org/status/#specification-service-workers
+const asyncCache = window.caches ? caches.open('mastodon-system') : Promise.reject();
function put(name, objects, onupdate, oncreate) {
return asyncDB.then(db => new Promise((resolve, reject) => {
From d1f34151aee564bb1e60ee48107797681c869a81 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Thu, 29 Mar 2018 19:08:34 +0200
Subject: [PATCH 012/442] Feature: Direct message from menu (#6956)
* Implement ability to send direct messages from the user menu
* Implement message warning users that direct messages are visible to all mentioned users
* Update locales
---
app/javascript/mastodon/actions/compose.js | 14 ++++++++++++++
.../features/account/components/action_bar.js | 3 +++
.../features/account_timeline/components/header.js | 6 ++++++
.../containers/header_container.js | 9 ++++++++-
.../compose/containers/warning_container.js | 7 ++++++-
app/javascript/mastodon/locales/ar.json | 2 ++
app/javascript/mastodon/locales/bg.json | 2 ++
app/javascript/mastodon/locales/ca.json | 2 ++
app/javascript/mastodon/locales/de.json | 2 ++
.../mastodon/locales/defaultMessages.json | 8 ++++++++
app/javascript/mastodon/locales/en.json | 2 ++
app/javascript/mastodon/locales/eo.json | 2 ++
app/javascript/mastodon/locales/es.json | 2 ++
app/javascript/mastodon/locales/fa.json | 2 ++
app/javascript/mastodon/locales/fi.json | 2 ++
app/javascript/mastodon/locales/fr.json | 2 ++
app/javascript/mastodon/locales/gl.json | 2 ++
app/javascript/mastodon/locales/he.json | 2 ++
app/javascript/mastodon/locales/hr.json | 2 ++
app/javascript/mastodon/locales/hu.json | 2 ++
app/javascript/mastodon/locales/hy.json | 2 ++
app/javascript/mastodon/locales/id.json | 2 ++
app/javascript/mastodon/locales/io.json | 2 ++
app/javascript/mastodon/locales/it.json | 2 ++
app/javascript/mastodon/locales/ja.json | 2 ++
app/javascript/mastodon/locales/ko.json | 2 ++
app/javascript/mastodon/locales/nl.json | 2 ++
app/javascript/mastodon/locales/no.json | 2 ++
app/javascript/mastodon/locales/oc.json | 2 ++
app/javascript/mastodon/locales/pl.json | 2 ++
app/javascript/mastodon/locales/pt-BR.json | 2 ++
app/javascript/mastodon/locales/pt.json | 2 ++
app/javascript/mastodon/locales/ru.json | 2 ++
app/javascript/mastodon/locales/sk.json | 2 ++
app/javascript/mastodon/locales/sr-Latn.json | 2 ++
app/javascript/mastodon/locales/sr.json | 2 ++
app/javascript/mastodon/locales/sv.json | 2 ++
app/javascript/mastodon/locales/th.json | 2 ++
app/javascript/mastodon/locales/tr.json | 2 ++
app/javascript/mastodon/locales/uk.json | 2 ++
app/javascript/mastodon/locales/zh-CN.json | 2 ++
app/javascript/mastodon/locales/zh-HK.json | 2 ++
app/javascript/mastodon/locales/zh-TW.json | 2 ++
app/javascript/mastodon/reducers/compose.js | 7 +++++++
44 files changed, 126 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index 5e7cdd270..2138f9426 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -15,6 +15,7 @@ export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS';
export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
export const COMPOSE_REPLY = 'COMPOSE_REPLY';
export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
+export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
export const COMPOSE_RESET = 'COMPOSE_RESET';
export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
@@ -91,6 +92,19 @@ export function mentionCompose(account, router) {
};
};
+export function directCompose(account, router) {
+ return (dispatch, getState) => {
+ dispatch({
+ type: COMPOSE_DIRECT,
+ account: account,
+ });
+
+ if (!getState().getIn(['compose', 'mounted'])) {
+ router.push('/statuses/new');
+ }
+ };
+};
+
export function submitCompose() {
return function (dispatch, getState) {
const status = getState().getIn(['compose', 'text'], '');
diff --git a/app/javascript/mastodon/features/account/components/action_bar.js b/app/javascript/mastodon/features/account/components/action_bar.js
index b538fa5fc..23dbf32bc 100644
--- a/app/javascript/mastodon/features/account/components/action_bar.js
+++ b/app/javascript/mastodon/features/account/components/action_bar.js
@@ -8,6 +8,7 @@ import { me } from '../../../initial_state';
const messages = defineMessages({
mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' },
+ direct: { id: 'account.direct', defaultMessage: 'Direct message @{name}' },
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
@@ -32,6 +33,7 @@ export default class ActionBar extends React.PureComponent {
onFollow: PropTypes.func,
onBlock: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired,
+ onDirect: PropTypes.func.isRequired,
onReblogToggle: PropTypes.func.isRequired,
onReport: PropTypes.func.isRequired,
onMute: PropTypes.func.isRequired,
@@ -53,6 +55,7 @@ export default class ActionBar extends React.PureComponent {
let extraInfo = '';
menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention });
+ menu.push({ text: intl.formatMessage(messages.direct, { name: account.get('username') }), action: this.props.onDirect });
if ('share' in navigator) {
menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare });
diff --git a/app/javascript/mastodon/features/account_timeline/components/header.js b/app/javascript/mastodon/features/account_timeline/components/header.js
index 6b88a7a0c..789999dce 100644
--- a/app/javascript/mastodon/features/account_timeline/components/header.js
+++ b/app/javascript/mastodon/features/account_timeline/components/header.js
@@ -16,6 +16,7 @@ export default class Header extends ImmutablePureComponent {
onFollow: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired,
+ onDirect: PropTypes.func.isRequired,
onReblogToggle: PropTypes.func.isRequired,
onReport: PropTypes.func.isRequired,
onMute: PropTypes.func.isRequired,
@@ -40,6 +41,10 @@ export default class Header extends ImmutablePureComponent {
this.props.onMention(this.props.account, this.context.router.history);
}
+ handleDirect = () => {
+ this.props.onDirect(this.props.account, this.context.router.history);
+ }
+
handleReport = () => {
this.props.onReport(this.props.account);
}
@@ -89,6 +94,7 @@ export default class Header extends ImmutablePureComponent {
account={account}
onBlock={this.handleBlock}
onMention={this.handleMention}
+ onDirect={this.handleDirect}
onReblogToggle={this.handleReblogToggle}
onReport={this.handleReport}
onMute={this.handleMute}
diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.js b/app/javascript/mastodon/features/account_timeline/containers/header_container.js
index b5e0e9a3f..214441b8a 100644
--- a/app/javascript/mastodon/features/account_timeline/containers/header_container.js
+++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.js
@@ -9,7 +9,10 @@ import {
unblockAccount,
unmuteAccount,
} from '../../../actions/accounts';
-import { mentionCompose } from '../../../actions/compose';
+import {
+ mentionCompose,
+ directCompose,
+} from '../../../actions/compose';
import { initMuteModal } from '../../../actions/mutes';
import { initReport } from '../../../actions/reports';
import { openModal } from '../../../actions/modal';
@@ -67,6 +70,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(mentionCompose(account, router));
},
+ onDirect (account, router) {
+ dispatch(directCompose(account, router));
+ },
+
onReblogToggle (account) {
if (account.getIn(['relationship', 'showing_reblogs'])) {
dispatch(followAccount(account.get('id'), false));
diff --git a/app/javascript/mastodon/features/compose/containers/warning_container.js b/app/javascript/mastodon/features/compose/containers/warning_container.js
index 8ee8ea190..efaa02e9e 100644
--- a/app/javascript/mastodon/features/compose/containers/warning_container.js
+++ b/app/javascript/mastodon/features/compose/containers/warning_container.js
@@ -10,15 +10,19 @@ const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\w*[a-zA-Z·]\w*)/i;
const mapStateToProps = state => ({
needsLockWarning: state.getIn(['compose', 'privacy']) === 'private' && !state.getIn(['accounts', me, 'locked']),
hashtagWarning: state.getIn(['compose', 'privacy']) !== 'public' && APPROX_HASHTAG_RE.test(state.getIn(['compose', 'text'])),
+ directMessageWarning: state.getIn(['compose', 'privacy']) === 'direct',
});
-const WarningWrapper = ({ needsLockWarning, hashtagWarning }) => {
+const WarningWrapper = ({ needsLockWarning, hashtagWarning, directMessageWarning }) => {
if (needsLockWarning) {
return }} />} />;
}
if (hashtagWarning) {
return } />;
}
+ if (directMessageWarning) {
+ return } />;
+ }
return null;
};
@@ -26,6 +30,7 @@ const WarningWrapper = ({ needsLockWarning, hashtagWarning }) => {
WarningWrapper.propTypes = {
needsLockWarning: PropTypes.bool,
hashtagWarning: PropTypes.bool,
+ directMessageWarning: PropTypes.bool,
};
export default connect(mapStateToProps)(WarningWrapper);
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 3d9620793..f9af062d0 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -2,6 +2,7 @@
"account.block": "حظر @{name}",
"account.block_domain": "إخفاء كل شيئ قادم من إسم النطاق {domain}",
"account.blocked": "محظور",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "قد لا تعكس المعلومات أدناه الملف الشخصي الكامل للمستخدم.",
"account.domain_blocked": "النطاق مخفي",
"account.edit_profile": "تعديل الملف الشخصي",
@@ -56,6 +57,7 @@
"column_header.unpin": "فك التدبيس",
"column_subheading.navigation": "التصفح",
"column_subheading.settings": "الإعدادات",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "هذا التبويق لن يُدرَج تحت أي وسم كان بما أنه غير مُدرَج. لا يُسمح بالبحث إلّا عن التبويقات العمومية عن طريق الوسوم.",
"compose_form.lock_disclaimer": "حسابك ليس {locked}. يمكن لأي شخص متابعتك و عرض المنشورات.",
"compose_form.lock_disclaimer.lock": "مقفل",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 39eb05f2a..58795ca37 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -2,6 +2,7 @@
"account.block": "Блокирай",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Редактирай профила си",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Settings",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 33545d86f..b0ce34c6b 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -2,6 +2,7 @@
"account.block": "Bloca @{name}",
"account.block_domain": "Amaga-ho tot de {domain}",
"account.blocked": "Bloquejat",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.",
"account.domain_blocked": "Domini ocult",
"account.edit_profile": "Edita el perfil",
@@ -56,6 +57,7 @@
"column_header.unpin": "No fixis",
"column_subheading.navigation": "Navegació",
"column_subheading.settings": "Configuració",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Aquest toot no es mostrarà en cap etiqueta ja que no està llistat. Només els toots públics poden ser cercats per etiqueta.",
"compose_form.lock_disclaimer": "El teu compte no està bloquejat {locked}. Tothom pot seguir-te i veure els teus missatges a seguidors.",
"compose_form.lock_disclaimer.lock": "blocat",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 7bdb6a3c6..eb0c5056a 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -2,6 +2,7 @@
"account.block": "@{name} blocken",
"account.block_domain": "Alles von {domain} verstecken",
"account.blocked": "Blockiert",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Das Profil wird möglicherweise unvollständig wiedergegeben.",
"account.domain_blocked": "Domain versteckt",
"account.edit_profile": "Profil bearbeiten",
@@ -56,6 +57,7 @@
"column_header.unpin": "Lösen",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Einstellungen",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Dieser Beitrag wird nicht unter einen dieser Hashtags sichtbar sein, solange er ungelistet ist. Bei einer Suche kann er nicht gefunden werden.",
"compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Wer dir folgen will, kann das jederzeit tun und dann auch deine privaten Beiträge sehen.",
"compose_form.lock_disclaimer.lock": "gesperrt",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 76b302f3a..1fe6861c9 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -380,6 +380,10 @@
"defaultMessage": "Mention @{name}",
"id": "account.mention"
},
+ {
+ "defaultMessage": "Direct message @{name}",
+ "id": "account.direct"
+ },
{
"defaultMessage": "Edit profile",
"id": "account.edit_profile"
@@ -804,6 +808,10 @@
{
"defaultMessage": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
"id": "compose_form.hashtag_warning"
+ },
+ {
+ "defaultMessage": "This toot will only be visible to all the mentioned users.",
+ "id": "compose_form.direct_message_warning"
}
],
"path": "app/javascript/mastodon/features/compose/containers/warning_container.json"
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index de44bd0db..d481596e0 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -2,6 +2,7 @@
"account.block": "Block @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Edit profile",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Settings",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 35d9edf2b..9b00edb00 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -2,6 +2,7 @@
"account.block": "Bloki @{name}",
"account.block_domain": "Kaŝi ĉion de {domain}",
"account.blocked": "Blokita",
+ "account.direct": "Direct Message @{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",
@@ -56,6 +57,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.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 nur por sekvantoj.",
"compose_form.lock_disclaimer.lock": "ŝlosita",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index e69938b0f..9f03b31c1 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -2,6 +2,7 @@
"account.block": "Bloquear",
"account.block_domain": "Ocultar todo de {domain}",
"account.blocked": "Bloqueado",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "La siguiente información del usuario puede estar incompleta.",
"account.domain_blocked": "Dominio oculto",
"account.edit_profile": "Editar perfil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Dejar de fijar",
"column_subheading.navigation": "Navegación",
"column_subheading.settings": "Ajustes",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Este toot no se mostrará bajo hashtags porque no es público. Sólo los toots públicos se pueden buscar por hashtag.",
"compose_form.lock_disclaimer": "Tu cuenta no está bloqueada. Todos pueden seguirte para ver tus toots solo para seguidores.",
"compose_form.lock_disclaimer.lock": "bloqueado",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index c9695d0a4..9421746b1 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -2,6 +2,7 @@
"account.block": "مسدودسازی @{name}",
"account.block_domain": "پنهانسازی همه چیز از سرور {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "اطلاعات زیر ممکن است نمایهٔ این کاربر را به تمامی نشان ندهد.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "ویرایش نمایه",
@@ -56,6 +57,7 @@
"column_header.unpin": "رهاکردن",
"column_subheading.navigation": "گشت و گذار",
"column_subheading.settings": "تنظیمات",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "حساب شما {locked} نیست. هر کسی میتواند پیگیر شما شود و نوشتههای ویژهٔ پیگیران شما را ببیند.",
"compose_form.lock_disclaimer.lock": "قفل",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index cbdffec10..fce441df4 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -2,6 +2,7 @@
"account.block": "Estä @{name}",
"account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}",
"account.blocked": "Estetty",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Alla olevat käyttäjän profiilitiedot saattavat olla epätäydellisiä.",
"account.domain_blocked": "Verkko-osoite piilotettu",
"account.edit_profile": "Muokkaa",
@@ -56,6 +57,7 @@
"column_header.unpin": "Poista kiinnitys",
"column_subheading.navigation": "Navigaatio",
"column_subheading.settings": "Asetukset",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Tämä töötti ei tule näkymään hashtag-hauissa, koska se ei näy julkisilla aikajanoilla. Vain julkisia tööttejä voi hakea hashtageilla.",
"compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille -postauksesi.",
"compose_form.lock_disclaimer.lock": "lukittu",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 8c56a7558..6eb34e644 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -2,6 +2,7 @@
"account.block": "Bloquer @{name}",
"account.block_domain": "Tout masquer venant de {domain}",
"account.blocked": "Bloqué",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Les données ci-dessous peuvent ne pas refléter ce profil dans sa totalité.",
"account.domain_blocked": "Domaine caché",
"account.edit_profile": "Modifier le profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Retirer",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Paramètres",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Ce pouet ne sera pas listé dans les recherches par hashtag car sa visibilité est réglée sur \"non-listé\". Seuls les pouets avec une visibilité \"publique\" peuvent être recherchés par hashtag.",
"compose_form.lock_disclaimer": "Votre compte n’est pas {locked}. Tout le monde peut vous suivre et voir vos pouets privés.",
"compose_form.lock_disclaimer.lock": "verrouillé",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index c5cedd60a..a0823b93f 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -2,6 +2,7 @@
"account.block": "Bloquear @{name}",
"account.block_domain": "Ocultar calquer contido de {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "A información inferior podería mostrar un perfil incompleto da usuaria.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Editar perfil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Soltar",
"column_subheading.navigation": "Navegación",
"column_subheading.settings": "Axustes",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Esta mensaxe non será listada baixo ningunha etiqueta xa que está marcada como non listada. Só os toots públicos poden buscarse por etiquetas.",
"compose_form.lock_disclaimer": "A súa conta non está {locked}. Calquera pode seguila para ver as súas mensaxes só-para-seguidoras.",
"compose_form.lock_disclaimer.lock": "bloqueado",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index fe6f9bbb1..0e2ee8da4 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -2,6 +2,7 @@
"account.block": "חסימת @{name}",
"account.block_domain": "להסתיר הכל מהקהילה {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "המידע להלן עשוי להיות לא עדכני או לא שלם.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "עריכת פרופיל",
@@ -56,6 +57,7 @@
"column_header.unpin": "שחרור קיבוע",
"column_subheading.navigation": "ניווט",
"column_subheading.settings": "אפשרויות",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "חשבונך אינו {locked}. כל אחד יוכל לעקוב אחריך כדי לקרוא את הודעותיך המיועדות לעוקבים בלבד.",
"compose_form.lock_disclaimer.lock": "נעול",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index 11cd1bff2..1e8ce8e29 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -2,6 +2,7 @@
"account.block": "Blokiraj @{name}",
"account.block_domain": "Sakrij sve sa {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Ovaj korisnik je sa druge instance. Ovaj broj bi mogao biti veći.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Uredi profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigacija",
"column_subheading.settings": "Postavke",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Tvoj račun nije {locked}. Svatko te može slijediti kako bi vidio postove namijenjene samo tvojim sljedbenicima.",
"compose_form.lock_disclaimer.lock": "zaključan",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 1ea65768a..deb17c6f4 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -2,6 +2,7 @@
"account.block": "@{name} letiltása",
"account.block_domain": "Minden elrejtése innen: {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Az alul található információk hiányosan mutathatják be a felhasználót.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Profil szerkesztése",
@@ -56,6 +57,7 @@
"column_header.unpin": "Kitűzés eltávolítása",
"column_subheading.navigation": "Navigáció",
"column_subheading.settings": "Beállítások",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Ezen tülkölés nem fog megjelenni semmilyen hashtag alatt mivel listázatlan. Csak a publikus tülkölések kereshetőek hashtag-el.",
"compose_form.lock_disclaimer": "Az ön fiókja nincs {locked}. Bárki követni tud, hogy megtekintse a kizárt követőknek szánt üzeneteid.",
"compose_form.lock_disclaimer.lock": "lezárva",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index e9638bf96..ee2055397 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -2,6 +2,7 @@
"account.block": "Արգելափակել @{name}֊ին",
"account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Ներքոհիշյալը կարող է ոչ ամբողջությամբ արտացոլել օգտատիրոջ էջի տվյալները։",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Խմբագրել անձնական էջը",
@@ -56,6 +57,7 @@
"column_header.unpin": "Հանել",
"column_subheading.navigation": "Նավարկություն",
"column_subheading.settings": "Կարգավորումներ",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Այս թութը չի հաշվառվի որեւէ պիտակի տակ, քանզի այն ծածուկ է։ Միայն հրապարակային թթերը հնարավոր է որոնել պիտակներով։",
"compose_form.lock_disclaimer": "Քո հաշիվը {locked} չէ։ Յուրաքանչյուր ոք կարող է հետեւել քեզ եւ տեսնել միայն հետեւողների համար նախատեսված գրառումները։",
"compose_form.lock_disclaimer.lock": "փակ",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index c8d8ebe76..cae3211ee 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -2,6 +2,7 @@
"account.block": "Blokir @{name}",
"account.block_domain": "Sembunyikan segalanya dari {domain}",
"account.blocked": "Terblokir",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Informasi di bawah mungkin tidak mencerminkan profil user secara lengkap.",
"account.domain_blocked": "Domain disembunyikan",
"account.edit_profile": "Ubah profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Lepaskan",
"column_subheading.navigation": "Navigasi",
"column_subheading.settings": "Pengaturan",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Toot ini tidak akan ada dalam daftar tagar manapun karena telah di set sebagai tidak terdaftar. Hanya postingan publik yang bisa dicari dengan tagar.",
"compose_form.lock_disclaimer": "Akun anda tidak {locked}. Semua orang dapat mengikuti anda untuk melihat postingan khusus untuk pengikut anda.",
"compose_form.lock_disclaimer.lock": "terkunci",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index a2e9af8ef..121d745ca 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -2,6 +2,7 @@
"account.block": "Blokusar @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Modifikar profilo",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Settings",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 40ea9b26d..5e57143a9 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -2,6 +2,7 @@
"account.block": "Blocca @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Modifica profilo",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Settings",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 08f5e7962..c14d6191f 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -2,6 +2,7 @@
"account.block": "@{name}さんをブロック",
"account.block_domain": "{domain}全体を非表示",
"account.blocked": "ブロック済み",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "以下の情報は不正確な可能性があります。",
"account.domain_blocked": "ドメイン非表示中",
"account.edit_profile": "プロフィールを編集",
@@ -56,6 +57,7 @@
"column_header.unpin": "ピン留めを外す",
"column_subheading.navigation": "ナビゲーション",
"column_subheading.settings": "設定",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "このトゥートは未収載なのでハッシュタグの一覧に表示されません。公開トゥートだけがハッシュタグで検索できます。",
"compose_form.lock_disclaimer": "あなたのアカウントは{locked}になっていません。誰でもあなたをフォローすることができ、フォロワー限定の投稿を見ることができます。",
"compose_form.lock_disclaimer.lock": "非公開",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index bde4397f3..fa15214c9 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -2,6 +2,7 @@
"account.block": "@{name}을 차단",
"account.block_domain": "{domain} 전체를 숨김",
"account.blocked": "차단 됨",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "여기 있는 정보는 유저의 프로파일을 정확히 반영하지 못 할 수도 있습니다.",
"account.domain_blocked": "도메인 숨겨짐",
"account.edit_profile": "프로필 편집",
@@ -56,6 +57,7 @@
"column_header.unpin": "고정 해제",
"column_subheading.navigation": "내비게이션",
"column_subheading.settings": "설정",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "이 툿은 어떤 해시태그로도 검색 되지 않습니다. 전체공개로 게시 된 툿만이 해시태그로 검색 될 수 있습니다.",
"compose_form.lock_disclaimer": "이 계정은 {locked}로 설정 되어 있지 않습니다. 누구나 이 계정을 팔로우 할 수 있으며, 팔로워 공개의 포스팅을 볼 수 있습니다.",
"compose_form.lock_disclaimer.lock": "비공개",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 140be0dca..ff827991d 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -2,6 +2,7 @@
"account.block": "Blokkeer @{name}",
"account.block_domain": "Negeer alles van {domain}",
"account.blocked": "Geblokkeerd",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "De informatie hieronder kan mogelijk een incompleet beeld geven van dit gebruikersprofiel.",
"account.domain_blocked": "Domein verborgen",
"account.edit_profile": "Profiel bewerken",
@@ -56,6 +57,7 @@
"column_header.unpin": "Losmaken",
"column_subheading.navigation": "Navigatie",
"column_subheading.settings": "Instellingen",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Deze toot valt niet onder een hashtag te bekijken, omdat deze niet op openbare tijdlijnen wordt getoond. Alleen openbare toots kunnen via hashtags gevonden worden.",
"compose_form.lock_disclaimer": "Jouw account is niet {locked}. Iedereen kan jou volgen en toots zien die je alleen aan volgers hebt gericht.",
"compose_form.lock_disclaimer.lock": "besloten",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 4d6ac133e..d3bc75708 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -2,6 +2,7 @@
"account.block": "Blokkér @{name}",
"account.block_domain": "Skjul alt fra {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Informasjonen nedenfor kan gi et ufullstendig bilde av brukerens profil.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Rediger profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Løsne",
"column_subheading.navigation": "Navigasjon",
"column_subheading.settings": "Innstillinger",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Denne tuten blir ikke listet under noen emneknagger da den er ulistet. Kun offentlige tuter kan søktes etter med emneknagg.",
"compose_form.lock_disclaimer": "Din konto er ikke {locked}. Hvem som helst kan følge deg og se dine private poster.",
"compose_form.lock_disclaimer.lock": "låst",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 24dfa9375..39ba31de3 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -2,6 +2,7 @@
"account.block": "Blocar @{name}",
"account.block_domain": "Tot amagar del domeni {domain}",
"account.blocked": "Blocat",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Aquelas informacions de perfil pòdon èsser incomplètas.",
"account.domain_blocked": "Domeni amagat",
"account.edit_profile": "Modificar lo perfil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Despenjar",
"column_subheading.navigation": "Navigacion",
"column_subheading.settings": "Paramètres",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Aqueste tut serà pas ligat a cap etiqueta estant qu’es pas listat. Òm pas cercar que los tuts publics per etiqueta.",
"compose_form.lock_disclaimer": "Vòstre compte es pas {locked}. Tot lo mond pòt vos sègre e veire los estatuts reservats als seguidors.",
"compose_form.lock_disclaimer.lock": "clavat",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 7262ce76b..d9490c518 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -2,6 +2,7 @@
"account.block": "Blokuj @{name}",
"account.block_domain": "Blokuj wszystko z {domain}",
"account.blocked": "Zablokowany",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Poniższe informacje mogą nie odwzorowywać bezbłędnie profilu użytkownika.",
"account.domain_blocked": "Ukryto domenę",
"account.edit_profile": "Edytuj profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Cofnij przypięcie",
"column_subheading.navigation": "Nawigacja",
"column_subheading.settings": "Ustawienia",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Ten wpis nie będzie widoczny pod podanymi hashtagami, ponieważ jest oznaczony jako niewidoczny. Tylko publiczne wpisy mogą zostać znalezione z użyciem hashtagów.",
"compose_form.lock_disclaimer": "Twoje konto nie jest {locked}. Każdy, kto Cię śledzi, może wyświetlać Twoje wpisy przeznaczone tylko dla śledzących.",
"compose_form.lock_disclaimer.lock": "zablokowane",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index dcaeaced9..3d42eedb3 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -2,6 +2,7 @@
"account.block": "Bloquear @{name}",
"account.block_domain": "Esconder tudo de {domain}",
"account.blocked": "Bloqueado",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "As informações abaixo podem refletir o perfil do usuário de maneira incompleta.",
"account.domain_blocked": "Domínio escondido",
"account.edit_profile": "Editar perfil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Desafixar",
"column_subheading.navigation": "Navegação",
"column_subheading.settings": "Configurações",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Esse toot não será listado em nenhuma hashtag por ser não listado. Somente toots públicos podem ser pesquisados por hashtag.",
"compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.",
"compose_form.lock_disclaimer.lock": "trancada",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index 4725a82da..5c93614a9 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -2,6 +2,7 @@
"account.block": "Bloquear @{name}",
"account.block_domain": "Esconder tudo do domínio {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "As informações abaixo podem refletir o perfil do usuário de forma incompleta.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Editar perfil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Desafixar",
"column_subheading.navigation": "Navegação",
"column_subheading.settings": "Preferências",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Esta pulbicacção não será listada em nenhuma hashtag por ser não listada. Somente publicações públicas podem ser pesquisadas por hashtag.",
"compose_form.lock_disclaimer": "A tua conta não está {locked}. Qualquer pessoa pode seguir-te e ver as publicações direcionadas apenas a seguidores.",
"compose_form.lock_disclaimer.lock": "bloqueada",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 8e7d36659..7dffbb210 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -2,6 +2,7 @@
"account.block": "Блокировать",
"account.block_domain": "Блокировать все с {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Нижеуказанная информация может не полностью отражать профиль пользователя.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Изменить профиль",
@@ -56,6 +57,7 @@
"column_header.unpin": "Открепить",
"column_subheading.navigation": "Навигация",
"column_subheading.settings": "Настройки",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Этот пост не будет показывается в поиске по хэштегу, т.к. он непубличный. Только публичные посты можно найти в поиске по хэштегу.",
"compose_form.lock_disclaimer": "Ваш аккаунт не {locked}. Любой человек может подписаться на Вас и просматривать посты для подписчиков.",
"compose_form.lock_disclaimer.lock": "закрыт",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index e3b323943..0a248d261 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -2,6 +2,7 @@
"account.block": "Blokovať @{name}",
"account.block_domain": "Ukryť všetko z {domain}",
"account.blocked": "Blokovaný/á",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Inofrmácie nižšie nemusia byť úplným odrazom uživateľovho účtu.",
"account.domain_blocked": "Doména ukrytá",
"account.edit_profile": "Upraviť profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Odopnúť",
"column_subheading.navigation": "Navigácia",
"column_subheading.settings": "Nastavenia",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Tento toot nebude zobrazený pod žiadným haštagom lebo nieje listovaný. Iba verejné tooty môžu byť nájdené podľa haštagu.",
"compose_form.lock_disclaimer": "Váš účet nie je zamknutý. Ktokoľvek ťa môže nasledovať a vidieť tvoje správy pre sledujúcich.",
"compose_form.lock_disclaimer.lock": "zamknutý",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index d38e8e3af..b9effce96 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -2,6 +2,7 @@
"account.block": "Blokiraj korisnika @{name}",
"account.block_domain": "Sakrij sve sa domena {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Navedene informacije možda ne odslikavaju korisnički profil u potpunosti.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Izmeni profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Otkači",
"column_subheading.navigation": "Navigacija",
"column_subheading.settings": "Postavke",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Vaš nalog nije {locked}. Svako može da Vas zaprati i da vidi objave namenjene samo Vašim pratiocima.",
"compose_form.lock_disclaimer.lock": "zaključan",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index 3be0c89ee..a6c5f220e 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -2,6 +2,7 @@
"account.block": "Блокирај корисника @{name}",
"account.block_domain": "Сакриј све са домена {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Наведене информације можда не одсликавају кориснички профил у потпуности.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Измени профил",
@@ -56,6 +57,7 @@
"column_header.unpin": "Откачи",
"column_subheading.navigation": "Навигација",
"column_subheading.settings": "Поставке",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Ваш налог није {locked}. Свако може да Вас запрати и да види објаве намењене само Вашим пратиоцима.",
"compose_form.lock_disclaimer.lock": "закључан",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index a13ba9847..6dc3d7a98 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -2,6 +2,7 @@
"account.block": "Blockera @{name}",
"account.block_domain": "Dölj allt från {domain}",
"account.blocked": "Blockerad",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Informationen nedan kan spegla användarens profil ofullständigt.",
"account.domain_blocked": "Domän gömd",
"account.edit_profile": "Redigera profil",
@@ -56,6 +57,7 @@
"column_header.unpin": "Ångra fäst",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Inställningar",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "Denna toot kommer inte att listas under någon hashtag eftersom den är onoterad. Endast offentliga toots kan sökas med hashtag.",
"compose_form.lock_disclaimer": "Ditt konto är inte {locked}. Vemsomhelst kan följa dig och även se dina inlägg skrivna för endast dina följare.",
"compose_form.lock_disclaimer.lock": "låst",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 59ff10b46..4de354007 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -2,6 +2,7 @@
"account.block": "Block @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Edit profile",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Settings",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index e83af319e..9d0affea4 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -2,6 +2,7 @@
"account.block": "Engelle @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Profili düzenle",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigasyon",
"column_subheading.settings": "Ayarlar",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Hesabınız {locked} değil. Sadece takipçilerle paylaştığınız gönderileri görebilmek için sizi herhangi bir kullanıcı takip edebilir.",
"compose_form.lock_disclaimer.lock": "kilitli",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index accc2d027..c49d3c7ae 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -2,6 +2,7 @@
"account.block": "Заблокувати",
"account.block_domain": "Заглушити {domain}",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Налаштування профілю",
@@ -56,6 +57,7 @@
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Навігація",
"column_subheading.settings": "Налаштування",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "Ваш акаунт не {locked}. Кожен може підписатися на Вас та бачити Ваші приватні пости.",
"compose_form.lock_disclaimer.lock": "приватний",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index b9a912fb0..e95cf81f4 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -2,6 +2,7 @@
"account.block": "屏蔽 @{name}",
"account.block_domain": "隐藏来自 {domain} 的内容",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "此处显示的信息可能不是全部内容。",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "修改个人资料",
@@ -56,6 +57,7 @@
"column_header.unpin": "取消固定",
"column_subheading.navigation": "导航",
"column_subheading.settings": "设置",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"compose_form.hashtag_warning": "这条嘟文被设置为“不公开”,因此它不会出现在任何话题标签的列表下。只有公开的嘟文才能通过话题标签进行搜索。",
"compose_form.lock_disclaimer": "你的帐户没有{locked}。任何人都可以在关注你后立即查看仅关注者可见的嘟文。",
"compose_form.lock_disclaimer.lock": "开启保护",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 91b1d00af..1801c838d 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -2,6 +2,7 @@
"account.block": "封鎖 @{name}",
"account.block_domain": "隱藏來自 {domain} 的一切文章",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "下列資料不一定完整。",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "修改個人資料",
@@ -56,6 +57,7 @@
"column_header.unpin": "取下",
"column_subheading.navigation": "瀏覽",
"column_subheading.settings": "設定",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "你的用戶狀態為「{locked}」,任何人都能立即關注你,然後看到「只有關注者能看」的文章。",
"compose_form.lock_disclaimer.lock": "公共",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 7e845c650..acbe6eb8e 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -2,6 +2,7 @@
"account.block": "封鎖 @{name}",
"account.block_domain": "隱藏來自 {domain} 的一切貼文",
"account.blocked": "Blocked",
+ "account.direct": "Direct Message @{name}",
"account.disclaimer_full": "下列資料不一定完整。",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "編輯用者資訊",
@@ -56,6 +57,7 @@
"column_header.unpin": "取下",
"column_subheading.navigation": "瀏覽",
"column_subheading.settings": "設定",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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.lock_disclaimer": "你的帳號沒有{locked}。任何人都可以關注你,看到發給關注者的貼文。",
"compose_form.lock_disclaimer.lock": "上鎖",
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index 5eadebb81..a48c46941 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -4,6 +4,7 @@ import {
COMPOSE_CHANGE,
COMPOSE_REPLY,
COMPOSE_REPLY_CANCEL,
+ COMPOSE_DIRECT,
COMPOSE_MENTION,
COMPOSE_SUBMIT_REQUEST,
COMPOSE_SUBMIT_SUCCESS,
@@ -262,6 +263,12 @@ export default function compose(state = initialState, action) {
.update('text', text => `${text}@${action.account.get('acct')} `)
.set('focusDate', new Date())
.set('idempotencyKey', uuid());
+ case COMPOSE_DIRECT:
+ return state
+ .update('text', text => `${text}@${action.account.get('acct')} `)
+ .set('privacy', 'direct')
+ .set('focusDate', new Date())
+ .set('idempotencyKey', uuid());
case COMPOSE_SUGGESTIONS_CLEAR:
return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null);
case COMPOSE_SUGGESTIONS_READY:
From 947eedcab2c263e92900b53d64b184c1af856d24 Mon Sep 17 00:00:00 2001
From: takayamaki
Date: Fri, 30 Mar 2018 10:04:04 +0900
Subject: [PATCH 013/442] update ja locale (#6965)
related https://github.com/tootsuite/mastodon/pull/6956
---
app/javascript/mastodon/locales/ja.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index c14d6191f..b03906df0 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -2,7 +2,7 @@
"account.block": "@{name}さんをブロック",
"account.block_domain": "{domain}全体を非表示",
"account.blocked": "ブロック済み",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "@{name}さんにダイレクトメッセージ",
"account.disclaimer_full": "以下の情報は不正確な可能性があります。",
"account.domain_blocked": "ドメイン非表示中",
"account.edit_profile": "プロフィールを編集",
@@ -57,7 +57,7 @@
"column_header.unpin": "ピン留めを外す",
"column_subheading.navigation": "ナビゲーション",
"column_subheading.settings": "設定",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "compose_form.direct_message_warning": "このトゥートはメンションされた人だけが見ることができます。",
"compose_form.hashtag_warning": "このトゥートは未収載なのでハッシュタグの一覧に表示されません。公開トゥートだけがハッシュタグで検索できます。",
"compose_form.lock_disclaimer": "あなたのアカウントは{locked}になっていません。誰でもあなたをフォローすることができ、フォロワー限定の投稿を見ることができます。",
"compose_form.lock_disclaimer.lock": "非公開",
From 47cee7cc8e47471b372630cd28d50c6284aad8b3 Mon Sep 17 00:00:00 2001
From: Pierre-Morgan Gate
Date: Fri, 30 Mar 2018 00:52:44 -0700
Subject: [PATCH 014/442] Upgrade charlock_holmes to version 0.7.6 (#6966)
This version fixes compilation errors when trying to build its native extension with ICU 61.
---
Gemfile | 2 +-
Gemfile.lock | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/Gemfile b/Gemfile
index 29fa9cde7..9e644e7ae 100644
--- a/Gemfile
+++ b/Gemfile
@@ -25,7 +25,7 @@ gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.5'
gem 'bootsnap'
gem 'browser'
-gem 'charlock_holmes', '~> 0.7.5'
+gem 'charlock_holmes', '~> 0.7.6'
gem 'iso-639'
gem 'chewy', '~> 5.0'
gem 'cld3', '~> 3.2.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index f68419d8e..a185a602e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -113,7 +113,7 @@ GEM
xpath (~> 2.0)
case_transform (0.2)
activesupport
- charlock_holmes (0.7.5)
+ charlock_holmes (0.7.6)
chewy (5.0.0)
activesupport (>= 4.0)
elasticsearch (>= 2.0.0)
@@ -632,7 +632,7 @@ DEPENDENCIES
capistrano-rbenv (~> 2.1)
capistrano-yarn (~> 2.0)
capybara (~> 2.15)
- charlock_holmes (~> 0.7.5)
+ charlock_holmes (~> 0.7.6)
chewy (~> 5.0)
cld3 (~> 3.2.0)
climate_control (~> 0.2)
From a6c129ddbdaaa84bc631d85eb248fb5a9fa7eb96 Mon Sep 17 00:00:00 2001
From: ThibG
Date: Fri, 30 Mar 2018 12:38:00 +0200
Subject: [PATCH 015/442] Add some UI for user-defined domain blocks (#6628)
* Keep list of blocked domains
Might be overkill, but I'm trying to follow the same logic as for blocked users
* Add basic domain block UI
* Add the domain blocks UI to Getting Started
* Fix undefined URL in `fetchDomainBlocks`
* Update all known users' domain_blocking relationship instead of just one's
---
.../mastodon/actions/domain_blocks.js | 66 ++++++++++++++++---
app/javascript/mastodon/components/domain.js | 42 ++++++++++++
.../mastodon/containers/domain_container.js | 33 ++++++++++
.../account_timeline/components/header.js | 4 +-
.../containers/header_container.js | 8 +--
.../mastodon/features/domain_blocks/index.js | 66 +++++++++++++++++++
.../features/getting_started/index.js | 2 +
app/javascript/mastodon/features/ui/index.js | 2 +
.../features/ui/util/async-components.js | 4 ++
.../mastodon/reducers/domain_lists.js | 23 +++++++
app/javascript/mastodon/reducers/index.js | 2 +
.../mastodon/reducers/relationships.js | 12 +++-
.../styles/mastodon/components.scss | 24 +++++++
13 files changed, 271 insertions(+), 17 deletions(-)
create mode 100644 app/javascript/mastodon/components/domain.js
create mode 100644 app/javascript/mastodon/containers/domain_container.js
create mode 100644 app/javascript/mastodon/features/domain_blocks/index.js
create mode 100644 app/javascript/mastodon/reducers/domain_lists.js
diff --git a/app/javascript/mastodon/actions/domain_blocks.js b/app/javascript/mastodon/actions/domain_blocks.js
index 44363697a..47e2df76b 100644
--- a/app/javascript/mastodon/actions/domain_blocks.js
+++ b/app/javascript/mastodon/actions/domain_blocks.js
@@ -12,12 +12,18 @@ export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST';
export const DOMAIN_BLOCKS_FETCH_SUCCESS = 'DOMAIN_BLOCKS_FETCH_SUCCESS';
export const DOMAIN_BLOCKS_FETCH_FAIL = 'DOMAIN_BLOCKS_FETCH_FAIL';
-export function blockDomain(domain, accountId) {
+export const DOMAIN_BLOCKS_EXPAND_REQUEST = 'DOMAIN_BLOCKS_EXPAND_REQUEST';
+export const DOMAIN_BLOCKS_EXPAND_SUCCESS = 'DOMAIN_BLOCKS_EXPAND_SUCCESS';
+export const DOMAIN_BLOCKS_EXPAND_FAIL = 'DOMAIN_BLOCKS_EXPAND_FAIL';
+
+export function blockDomain(domain) {
return (dispatch, getState) => {
dispatch(blockDomainRequest(domain));
api(getState).post('/api/v1/domain_blocks', { domain }).then(() => {
- dispatch(blockDomainSuccess(domain, accountId));
+ const at_domain = '@' + domain;
+ const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
+ dispatch(blockDomainSuccess(domain, accounts));
}).catch(err => {
dispatch(blockDomainFail(domain, err));
});
@@ -31,11 +37,11 @@ export function blockDomainRequest(domain) {
};
};
-export function blockDomainSuccess(domain, accountId) {
+export function blockDomainSuccess(domain, accounts) {
return {
type: DOMAIN_BLOCK_SUCCESS,
domain,
- accountId,
+ accounts,
};
};
@@ -47,12 +53,14 @@ export function blockDomainFail(domain, error) {
};
};
-export function unblockDomain(domain, accountId) {
+export function unblockDomain(domain) {
return (dispatch, getState) => {
dispatch(unblockDomainRequest(domain));
api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
- dispatch(unblockDomainSuccess(domain, accountId));
+ const at_domain = '@' + domain;
+ const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
+ dispatch(unblockDomainSuccess(domain, accounts));
}).catch(err => {
dispatch(unblockDomainFail(domain, err));
});
@@ -66,11 +74,11 @@ export function unblockDomainRequest(domain) {
};
};
-export function unblockDomainSuccess(domain, accountId) {
+export function unblockDomainSuccess(domain, accounts) {
return {
type: DOMAIN_UNBLOCK_SUCCESS,
domain,
- accountId,
+ accounts,
};
};
@@ -86,7 +94,7 @@ export function fetchDomainBlocks() {
return (dispatch, getState) => {
dispatch(fetchDomainBlocksRequest());
- api(getState).get().then(response => {
+ api(getState).get('/api/v1/domain_blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => {
@@ -115,3 +123,43 @@ export function fetchDomainBlocksFail(error) {
error,
};
};
+
+export function expandDomainBlocks() {
+ return (dispatch, getState) => {
+ const url = getState().getIn(['domain_lists', 'blocks', 'next']);
+
+ if (url === null) {
+ return;
+ }
+
+ dispatch(expandDomainBlocksRequest());
+
+ api(getState).get(url).then(response => {
+ const next = getLinks(response).refs.find(link => link.rel === 'next');
+ dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null));
+ }).catch(err => {
+ dispatch(expandDomainBlocksFail(err));
+ });
+ };
+};
+
+export function expandDomainBlocksRequest() {
+ return {
+ type: DOMAIN_BLOCKS_EXPAND_REQUEST,
+ };
+};
+
+export function expandDomainBlocksSuccess(domains, next) {
+ return {
+ type: DOMAIN_BLOCKS_EXPAND_SUCCESS,
+ domains,
+ next,
+ };
+};
+
+export function expandDomainBlocksFail(error) {
+ return {
+ type: DOMAIN_BLOCKS_EXPAND_FAIL,
+ error,
+ };
+};
diff --git a/app/javascript/mastodon/components/domain.js b/app/javascript/mastodon/components/domain.js
new file mode 100644
index 000000000..f657cb8d2
--- /dev/null
+++ b/app/javascript/mastodon/components/domain.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import IconButton from './icon_button';
+import { defineMessages, injectIntl } from 'react-intl';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+
+const messages = defineMessages({
+ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
+});
+
+@injectIntl
+export default class Account extends ImmutablePureComponent {
+
+ static propTypes = {
+ domain: PropTypes.string,
+ onUnblockDomain: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
+ };
+
+ handleDomainUnblock = () => {
+ this.props.onUnblockDomain(this.props.domain);
+ }
+
+ render () {
+ const { domain, intl } = this.props;
+
+ return (
+
alert("Hello")'
end
+
+ context 'with custom_emojify option' do
+ let!(:emoji) { Fabricate(:custom_emoji, domain: remote_account.domain) }
+
+ before { remote_account.note = text }
+
+ subject { Formatter.instance.simplified_format(remote_account, custom_emojify: true) }
+
+ context 'with emoji at the start' do
+ let(:text) { '
:coolcat: Beep boop ' }
+
+ it 'converts shortcode to image tag' do
+ is_expected.to match(/
Beep :coolcat: boop
' }
+
+ it 'converts shortcode to image tag' do
+ is_expected.to match(/Beep :coolcat::coolcat:
' }
+
+ it 'does not touch the shortcodes' do
+ is_expected.to match(/
:coolcat::coolcat:<\/p>/)
+ end
+ end
+
+ context 'with emoji at the end' do
+ let(:text) { '
Beep boop :coolcat:
' }
+
+ it 'converts shortcode to image tag' do
+ is_expected.to match(/
Date: Mon, 2 Apr 2018 02:09:50 +0200
Subject: [PATCH 025/442] Fix unpermitted parameters warning when generating
pagination URLs (#6995)
---
app/controllers/api/v1/accounts/follower_accounts_controller.rb | 2 +-
.../api/v1/accounts/following_accounts_controller.rb | 2 +-
app/controllers/api/v1/accounts/statuses_controller.rb | 2 +-
app/controllers/api/v1/blocks_controller.rb | 2 +-
app/controllers/api/v1/domain_blocks_controller.rb | 2 +-
app/controllers/api/v1/favourites_controller.rb | 2 +-
app/controllers/api/v1/follow_requests_controller.rb | 2 +-
app/controllers/api/v1/lists/accounts_controller.rb | 2 +-
app/controllers/api/v1/mutes_controller.rb | 2 +-
app/controllers/api/v1/notifications_controller.rb | 2 +-
.../api/v1/statuses/favourited_by_accounts_controller.rb | 2 +-
.../api/v1/statuses/reblogged_by_accounts_controller.rb | 2 +-
app/controllers/api/v1/statuses_controller.rb | 2 +-
app/controllers/api/v1/timelines/home_controller.rb | 2 +-
app/controllers/api/v1/timelines/list_controller.rb | 2 +-
app/controllers/api/v1/timelines/public_controller.rb | 2 +-
app/controllers/api/v1/timelines/tag_controller.rb | 2 +-
17 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index 80b0bef40..c4f600c54 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -63,6 +63,6 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index 55cffdf37..90b1f7fc5 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -63,6 +63,6 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 1e1511a7b..cbcc7ef04 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -69,7 +69,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit, :only_media, :exclude_replies).merge(core_params)
+ params.slice(:limit, :only_media, :exclude_replies).permit(:limit, :only_media, :exclude_replies).merge(core_params)
end
def insert_pagination_headers
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index 3a6690766..a39701340 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -57,6 +57,6 @@ class Api::V1::BlocksController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb
index e93dc603b..ae6ad7936 100644
--- a/app/controllers/api/v1/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/domain_blocks_controller.rb
@@ -67,7 +67,7 @@ class Api::V1::DomainBlocksController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
def domain_block_params
diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb
index 9d73bb337..b4265ed34 100644
--- a/app/controllers/api/v1/favourites_controller.rb
+++ b/app/controllers/api/v1/favourites_controller.rb
@@ -66,6 +66,6 @@ class Api::V1::FavouritesController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/follow_requests_controller.rb b/app/controllers/api/v1/follow_requests_controller.rb
index b9f50d784..d5c7c565a 100644
--- a/app/controllers/api/v1/follow_requests_controller.rb
+++ b/app/controllers/api/v1/follow_requests_controller.rb
@@ -71,6 +71,6 @@ class Api::V1::FollowRequestsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/lists/accounts_controller.rb b/app/controllers/api/v1/lists/accounts_controller.rb
index c29c73b3e..f2bded851 100644
--- a/app/controllers/api/v1/lists/accounts_controller.rb
+++ b/app/controllers/api/v1/lists/accounts_controller.rb
@@ -88,7 +88,7 @@ class Api::V1::Lists::AccountsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
def unlimited?
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index 0c43cb943..c457408ba 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -59,6 +59,6 @@ class Api::V1::MutesController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index 8910b77e9..ebbe0b292 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -82,6 +82,6 @@ class Api::V1::NotificationsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit, exclude_types: []).merge(core_params)
+ params.slice(:limit, :exclude_types).permit(:limit, exclude_types: []).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
index f95cf9457..3fe304153 100644
--- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
@@ -77,6 +77,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index 175217e6e..b065db2c7 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -74,6 +74,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
end
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index 544a4ce21..28c28592a 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -76,7 +76,7 @@ class Api::V1::StatusesController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
def authorize_if_got_token
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb
index bbbcf7f90..cde4e8420 100644
--- a/app/controllers/api/v1/timelines/home_controller.rb
+++ b/app/controllers/api/v1/timelines/home_controller.rb
@@ -43,7 +43,7 @@ class Api::V1::Timelines::HomeController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:local, :limit).merge(core_params)
+ params.slice(:local, :limit).permit(:local, :limit).merge(core_params)
end
def next_path
diff --git a/app/controllers/api/v1/timelines/list_controller.rb b/app/controllers/api/v1/timelines/list_controller.rb
index f5db71e46..06d596c08 100644
--- a/app/controllers/api/v1/timelines/list_controller.rb
+++ b/app/controllers/api/v1/timelines/list_controller.rb
@@ -45,7 +45,7 @@ class Api::V1::Timelines::ListController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:limit).merge(core_params)
+ params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path
diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
index d7d70b94d..13fe015b7 100644
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ b/app/controllers/api/v1/timelines/public_controller.rb
@@ -45,7 +45,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:local, :limit, :only_media).merge(core_params)
+ params.slice(:local, :limit, :only_media).permit(:local, :limit, :only_media).merge(core_params)
end
def next_path
diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb
index eb32611ad..7de49a5ed 100644
--- a/app/controllers/api/v1/timelines/tag_controller.rb
+++ b/app/controllers/api/v1/timelines/tag_controller.rb
@@ -54,7 +54,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
end
def pagination_params(core_params)
- params.permit(:local, :limit, :only_media).merge(core_params)
+ params.slice(:local, :limit, :only_media).permit(:local, :limit, :only_media).merge(core_params)
end
def next_path
From f890d2a766ae4c7fd8611dd4f3a15a13408f68c3 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Mon, 2 Apr 2018 02:10:53 +0200
Subject: [PATCH 026/442] Support all ActivityPub actor types (#6997)
Fix #6973
---
app/services/activitypub/fetch_remote_account_service.rb | 4 +++-
app/services/activitypub/fetch_remote_key_service.rb | 4 ++--
app/services/fetch_atom_service.rb | 2 +-
app/services/resolve_account_service.rb | 2 +-
app/services/resolve_url_service.rb | 2 +-
5 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb
index d6ba625a9..5024853ca 100644
--- a/app/services/activitypub/fetch_remote_account_service.rb
+++ b/app/services/activitypub/fetch_remote_account_service.rb
@@ -3,6 +3,8 @@
class ActivityPub::FetchRemoteAccountService < BaseService
include JsonLdHelper
+ SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze
+
# Should be called when uri has already been checked for locality
# Does a WebFinger roundtrip on each call
def call(uri, id: true, prefetched_body: nil)
@@ -54,6 +56,6 @@ class ActivityPub::FetchRemoteAccountService < BaseService
end
def expected_type?
- @json['type'] == 'Person'
+ SUPPORTED_TYPES.include?(@json['type'])
end
end
diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb
index ce1048fee..41837d462 100644
--- a/app/services/activitypub/fetch_remote_key_service.rb
+++ b/app/services/activitypub/fetch_remote_key_service.rb
@@ -43,7 +43,7 @@ class ActivityPub::FetchRemoteKeyService < BaseService
end
def person?
- @json['type'] == 'Person'
+ ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(@json['type'])
end
def public_key?
@@ -55,6 +55,6 @@ class ActivityPub::FetchRemoteKeyService < BaseService
end
def confirmed_owner?
- @owner['type'] == 'Person' && value_or_id(@owner['publicKey']) == @json['id']
+ ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(@owner['type']) && value_or_id(@owner['publicKey']) == @json['id']
end
end
diff --git a/app/services/fetch_atom_service.rb b/app/services/fetch_atom_service.rb
index 87076cc07..0444baf74 100644
--- a/app/services/fetch_atom_service.rb
+++ b/app/services/fetch_atom_service.rb
@@ -42,7 +42,7 @@ class FetchAtomService < BaseService
elsif ['application/activity+json', 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'].include?(response.mime_type)
body = response.body_with_limit
json = body_to_json(body)
- if supported_context?(json) && json['type'] == 'Person' && json['inbox'].present?
+ if supported_context?(json) && ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(json['type']) && json['inbox'].present?
[json['id'], { prefetched_body: body, id: true }, :activitypub]
elsif supported_context?(json) && expected_type?(json)
[json['id'], { prefetched_body: body, id: true }, :activitypub]
diff --git a/app/services/resolve_account_service.rb b/app/services/resolve_account_service.rb
index 744ea24f4..8cba88f01 100644
--- a/app/services/resolve_account_service.rb
+++ b/app/services/resolve_account_service.rb
@@ -189,7 +189,7 @@ class ResolveAccountService < BaseService
return @actor_json if defined?(@actor_json)
json = fetch_resource(actor_url, false)
- @actor_json = supported_context?(json) && json['type'] == 'Person' ? json : nil
+ @actor_json = supported_context?(json) && ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES.include?(json['type']) ? json : nil
end
def atom
diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb
index 9499dc286..c19b568cb 100644
--- a/app/services/resolve_url_service.rb
+++ b/app/services/resolve_url_service.rb
@@ -17,7 +17,7 @@ class ResolveURLService < BaseService
def process_url
case type
- when 'Person'
+ when 'Application', 'Group', 'Organization', 'Person', 'Service'
FetchRemoteAccountService.new.call(atom_url, body, protocol)
when 'Note', 'Article', 'Image', 'Video'
FetchRemoteStatusService.new.call(atom_url, body, protocol)
From 24611d8deb8eb31e3af1aa2035aab29fbd4510f9 Mon Sep 17 00:00:00 2001
From: luzi82
Date: Mon, 2 Apr 2018 18:11:37 +0800
Subject: [PATCH 027/442] i18n: update zh-HK translation (#7004)
* i18n: update zh-HK translation
* i18n: update zh-HK translation
* i18n-tasks normalize
---
app/javascript/mastodon/locales/zh-HK.json | 172 ++++++++++-----------
config/locales/simple_form.zh-HK.yml | 2 +
config/locales/zh-HK.yml | 31 +++-
3 files changed, 118 insertions(+), 87 deletions(-)
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 0504a8c7a..1cbc9f1c5 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -1,36 +1,36 @@
{
"account.block": "封鎖 @{name}",
"account.block_domain": "隱藏來自 {domain} 的一切文章",
- "account.blocked": "Blocked",
- "account.direct": "Direct Message @{name}",
+ "account.blocked": "封鎖",
+ "account.direct": "私訊 @{name}",
"account.disclaimer_full": "下列資料不一定完整。",
- "account.domain_blocked": "Domain hidden",
+ "account.domain_blocked": "服務站被隱藏",
"account.edit_profile": "修改個人資料",
"account.follow": "關注",
"account.followers": "關注的人",
"account.follows": "正關注",
"account.follows_you": "關注你",
- "account.hide_reblogs": "Hide boosts from @{name}",
+ "account.hide_reblogs": "隱藏 @{name} 的轉推",
"account.media": "媒體",
"account.mention": "提及 @{name}",
- "account.moved_to": "{name} has moved to:",
+ "account.moved_to": "{name} 已經遷移到:",
"account.mute": "將 @{name} 靜音",
- "account.mute_notifications": "Mute notifications from @{name}",
- "account.muted": "Muted",
+ "account.mute_notifications": "將來自 @{name} 的通知靜音",
+ "account.muted": "靜音",
"account.posts": "文章",
- "account.posts_with_replies": "Toots with replies",
+ "account.posts_with_replies": "包含回覆的文章",
"account.report": "舉報 @{name}",
"account.requested": "等候審批",
"account.share": "分享 @{name} 的個人資料",
- "account.show_reblogs": "Show boosts from @{name}",
+ "account.show_reblogs": "顯示 @{name} 的推文",
"account.unblock": "解除對 @{name} 的封鎖",
"account.unblock_domain": "不再隱藏 {domain}",
"account.unfollow": "取消關注",
"account.unmute": "取消 @{name} 的靜音",
- "account.unmute_notifications": "Unmute notifications from @{name}",
+ "account.unmute_notifications": "取消來自 @{name} 通知的靜音",
"account.view_full_profile": "查看完整資料",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "發生不可預期的錯誤。",
+ "alert.unexpected.title": "噢!",
"boost_modal.combo": "如你想在下次路過這顯示,請按{combo},",
"bundle_column_error.body": "加載本組件出錯。",
"bundle_column_error.retry": "重試",
@@ -40,11 +40,11 @@
"bundle_modal_error.retry": "重試",
"column.blocks": "封鎖用戶",
"column.community": "本站時間軸",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "隱藏的服務站",
"column.favourites": "最愛的文章",
"column.follow_requests": "關注請求",
"column.home": "主頁",
- "column.lists": "Lists",
+ "column.lists": "列表",
"column.mutes": "靜音名單",
"column.notifications": "通知",
"column.pins": "置頂文章",
@@ -58,25 +58,25 @@
"column_header.unpin": "取下",
"column_subheading.navigation": "瀏覽",
"column_subheading.settings": "設定",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
- "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.direct_message_warning": "這文章只有被提及的用戶才可以看到。",
+ "compose_form.hashtag_warning": "這文章因為不是公開,所以不會被標籤搜索。只有公開的文章才會被標籤搜索。",
"compose_form.lock_disclaimer": "你的用戶狀態為「{locked}」,任何人都能立即關注你,然後看到「只有關注者能看」的文章。",
"compose_form.lock_disclaimer.lock": "公共",
"compose_form.placeholder": "你在想甚麼?",
"compose_form.publish": "發文",
"compose_form.publish_loud": "{publish}!",
- "compose_form.sensitive.marked": "Media is marked as sensitive",
- "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
- "compose_form.spoiler.marked": "Text is hidden behind warning",
- "compose_form.spoiler.unmarked": "Text is not hidden",
+ "compose_form.sensitive.marked": "媒體被標示為敏感",
+ "compose_form.sensitive.unmarked": "媒體沒有被標示為敏感",
+ "compose_form.spoiler.marked": "文字被警告隱藏",
+ "compose_form.spoiler.unmarked": "文字沒有被隱藏",
"compose_form.spoiler_placeholder": "敏感警告訊息",
"confirmation_modal.cancel": "取消",
"confirmations.block.confirm": "封鎖",
"confirmations.block.message": "你確定要封鎖{name}嗎?",
"confirmations.delete.confirm": "刪除",
"confirmations.delete.message": "你確定要刪除{name}嗎?",
- "confirmations.delete_list.confirm": "Delete",
- "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
+ "confirmations.delete_list.confirm": "刪除",
+ "confirmations.delete_list.message": "你確定要永久刪除這列表嗎?",
"confirmations.domain_block.confirm": "隱藏整個網站",
"confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或靜音幾個特定目標就好。",
"confirmations.mute.confirm": "靜音",
@@ -86,7 +86,7 @@
"embed.instructions": "要內嵌此文章,請將以下代碼貼進你的網站。",
"embed.preview": "看上去會是這樣:",
"emoji_button.activity": "活動",
- "emoji_button.custom": "Custom",
+ "emoji_button.custom": "自訂",
"emoji_button.flags": "旗幟",
"emoji_button.food": "飲飲食食",
"emoji_button.label": "加入表情符號",
@@ -94,9 +94,9 @@
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "物品",
"emoji_button.people": "人物",
- "emoji_button.recent": "Frequently used",
+ "emoji_button.recent": "常用",
"emoji_button.search": "搜尋…",
- "emoji_button.search_results": "Search results",
+ "emoji_button.search_results": "搜尋結果",
"emoji_button.symbols": "符號",
"emoji_button.travel": "旅遊景物",
"empty_column.community": "本站時間軸暫時未有內容,快文章來搶頭香啊!",
@@ -119,48 +119,48 @@
"home.column_settings.show_reblogs": "顯示被轉推的文章",
"home.column_settings.show_replies": "顯示回應文章",
"home.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",
- "keyboard_shortcuts.description": "Description",
- "keyboard_shortcuts.down": "to move down in the list",
- "keyboard_shortcuts.enter": "to open status",
- "keyboard_shortcuts.favourite": "to 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.toot": "to start a brand new toot",
- "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
- "keyboard_shortcuts.up": "to move up in the list",
+ "keyboard_shortcuts.back": "後退",
+ "keyboard_shortcuts.boost": "轉推",
+ "keyboard_shortcuts.column": "把標示移動到其中一列",
+ "keyboard_shortcuts.compose": "把標示移動到文字輸入區",
+ "keyboard_shortcuts.description": "描述",
+ "keyboard_shortcuts.down": "在列表往下移動",
+ "keyboard_shortcuts.enter": "打開文章",
+ "keyboard_shortcuts.favourite": "收藏",
+ "keyboard_shortcuts.heading": "鍵盤快速鍵",
+ "keyboard_shortcuts.hotkey": "快速鍵",
+ "keyboard_shortcuts.legend": "顯示這個說明",
+ "keyboard_shortcuts.mention": "提及作者",
+ "keyboard_shortcuts.reply": "回覆",
+ "keyboard_shortcuts.search": "把標示移動到搜索",
+ "keyboard_shortcuts.toot": "新的推文",
+ "keyboard_shortcuts.unfocus": "把標示移離文字輸入和搜索",
+ "keyboard_shortcuts.up": "在列表往上移動",
"lightbox.close": "關閉",
"lightbox.next": "繼續",
"lightbox.previous": "回退",
- "lists.account.add": "Add to list",
- "lists.account.remove": "Remove from list",
- "lists.delete": "Delete list",
- "lists.edit": "Edit list",
- "lists.new.create": "Add list",
- "lists.new.title_placeholder": "New list title",
- "lists.search": "Search among people you follow",
- "lists.subheading": "Your lists",
+ "lists.account.add": "新增到列表",
+ "lists.account.remove": "從列表刪除",
+ "lists.delete": "刪除列表",
+ "lists.edit": "編輯列表",
+ "lists.new.create": "新增列表",
+ "lists.new.title_placeholder": "新列表標題",
+ "lists.search": "從你關注的用戶中搜索",
+ "lists.subheading": "列表",
"loading_indicator.label": "載入中...",
"media_gallery.toggle_visible": "打開或關上",
"missing_indicator.label": "找不到內容",
- "missing_indicator.sublabel": "This resource could not be found",
- "mute_modal.hide_notifications": "Hide notifications from this user?",
+ "missing_indicator.sublabel": "無法找到內容",
+ "mute_modal.hide_notifications": "隱藏來自這用戶的通知嗎?",
"navigation_bar.blocks": "被你封鎖的用戶",
"navigation_bar.community_timeline": "本站時間軸",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "隱藏的服務站",
"navigation_bar.edit_profile": "修改個人資料",
"navigation_bar.favourites": "最愛的內容",
"navigation_bar.follow_requests": "關注請求",
"navigation_bar.info": "關於本服務站",
- "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
- "navigation_bar.lists": "Lists",
+ "navigation_bar.keyboard_shortcuts": "鍵盤快速鍵",
+ "navigation_bar.lists": "列表",
"navigation_bar.logout": "登出",
"navigation_bar.mutes": "被你靜音的用戶",
"navigation_bar.pins": "置頂文章",
@@ -187,8 +187,8 @@
"onboarding.page_four.home": "「主頁」顯示你所關注用戶的文章",
"onboarding.page_four.notifications": "「通知」欄顯示你和其他人的互動。",
"onboarding.page_one.federation": "Mastodon(萬象社交)是由一批獨立網站組成的龐大網絡,我們將這些獨立又互連網站稱為「服務站」(instance)",
- "onboarding.page_one.full_handle": "Your full handle",
- "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
+ "onboarding.page_one.full_handle": "你的帳號全名",
+ "onboarding.page_one.handle_hint": "朋友可以從這個帳號全名找到你",
"onboarding.page_one.welcome": "歡迎使用 Mastodon(萬象社交)",
"onboarding.page_six.admin": "你服務站的管理員是{admin}",
"onboarding.page_six.almost_done": "差不多了……",
@@ -211,33 +211,33 @@
"privacy.public.short": "公共",
"privacy.unlisted.long": "公開,但不在公共時間軸顯示",
"privacy.unlisted.short": "公開",
- "regeneration_indicator.label": "Loading…",
- "regeneration_indicator.sublabel": "Your home feed is being prepared!",
- "relative_time.days": "{number}d",
- "relative_time.hours": "{number}h",
- "relative_time.just_now": "now",
- "relative_time.minutes": "{number}m",
- "relative_time.seconds": "{number}s",
+ "regeneration_indicator.label": "載入中……",
+ "regeneration_indicator.sublabel": "你的主頁時間軸正在準備中!",
+ "relative_time.days": "{number}日",
+ "relative_time.hours": "{number}小時",
+ "relative_time.just_now": "剛剛",
+ "relative_time.minutes": "{number}分鐘",
+ "relative_time.seconds": "{number}秒",
"reply_indicator.cancel": "取消",
- "report.forward": "Forward to {target}",
- "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
- "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
+ "report.forward": "轉寄到 {target}",
+ "report.forward_hint": "這個帳戶屬於其他服務站。要向該服務站發送匿名的舉報訊息嗎?",
+ "report.hint": "這訊息會發送到你服務站的管理員。你可以提供舉報這個帳戶的理由:",
"report.placeholder": "額外訊息",
"report.submit": "提交",
"report.target": "舉報",
"search.placeholder": "搜尋",
- "search_popout.search_format": "Advanced search format",
- "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": "status",
- "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
- "search_popout.tips.user": "user",
- "search_results.accounts": "People",
- "search_results.hashtags": "Hashtags",
- "search_results.statuses": "Toots",
+ "search_popout.search_format": "高級搜索格式",
+ "search_popout.tips.full_text": "輸入簡單的文字,搜索由你發放、收藏、轉推和提及你的文章,以及符合的用戶名稱,帳號名稱和標籤。",
+ "search_popout.tips.hashtag": "標籤",
+ "search_popout.tips.status": "文章",
+ "search_popout.tips.text": "輸入簡單的文字,搜索符合的用戶名稱,帳號名稱和標籤。",
+ "search_popout.tips.user": "用戶",
+ "search_results.accounts": "使用者",
+ "search_results.hashtags": "標籤",
+ "search_results.statuses": "文章",
"search_results.total": "{count, number} 項結果",
"standalone.public_title": "站點一瞥…",
- "status.block": "Block @{name}",
+ "status.block": "封鎖 @{name}",
"status.cannot_reblog": "這篇文章無法被轉推",
"status.delete": "刪除",
"status.embed": "鑲嵌",
@@ -245,12 +245,12 @@
"status.load_more": "載入更多",
"status.media_hidden": "隱藏媒體內容",
"status.mention": "提及 @{name}",
- "status.more": "More",
- "status.mute": "Mute @{name}",
+ "status.more": "更多",
+ "status.mute": "把 @{name} 靜音",
"status.mute_conversation": "靜音對話",
"status.open": "展開文章",
"status.pin": "置頂到資料頁",
- "status.pinned": "Pinned toot",
+ "status.pinned": "置頂文章",
"status.reblog": "轉推",
"status.reblogged_by": "{name} 轉推",
"status.reply": "回應",
@@ -258,22 +258,22 @@
"status.report": "舉報 @{name}",
"status.sensitive_toggle": "點擊顯示",
"status.sensitive_warning": "敏感內容",
- "status.share": "Share",
+ "status.share": "分享",
"status.show_less": "減少顯示",
- "status.show_less_all": "Show less for all",
+ "status.show_less_all": "減少顯示這類文章",
"status.show_more": "顯示更多",
- "status.show_more_all": "Show more for all",
+ "status.show_more_all": "顯示更多這類文章",
"status.unmute_conversation": "解禁對話",
"status.unpin": "解除置頂",
"tabs_bar.federated_timeline": "跨站",
"tabs_bar.home": "主頁",
"tabs_bar.local_timeline": "本站",
"tabs_bar.notifications": "通知",
- "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
+ "ui.beforeunload": "如果你現在離開 Mastodon,你的草稿內容將會被丟棄。",
"upload_area.title": "將檔案拖放至此上載",
"upload_button.label": "上載媒體檔案",
- "upload_form.description": "Describe for the visually impaired",
- "upload_form.focus": "Crop",
+ "upload_form.description": "為視覺障礙人士添加文字說明",
+ "upload_form.focus": "裁切",
"upload_form.undo": "還原",
"upload_progress.label": "上載中……",
"video.close": "關閉影片",
diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml
index 01ba61fdf..da0292a90 100644
--- a/config/locales/simple_form.zh-HK.yml
+++ b/config/locales/simple_form.zh-HK.yml
@@ -41,6 +41,7 @@ zh-HK:
setting_default_privacy: 文章預設為
setting_default_sensitive: 預設我的內容為敏感內容
setting_delete_modal: 刪推前詢問我
+ setting_display_sensitive_media: 預設我的媒體為敏感內容
setting_noindex: 阻止搜尋引擎檢索
setting_reduce_motion: 減低動畫效果
setting_system_font_ui: 使用系統預設字型
@@ -49,6 +50,7 @@ zh-HK:
severity: 等級
type: 匯入資料類型
username: 用戶名稱
+ username_or_email: 用戶名稱或電郵
interactions:
must_be_follower: 隱藏沒有關注你的用戶的通知
must_be_following: 隱藏你不關注的用戶的通知
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index cc1cade1e..5c1feabfc 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -101,7 +101,7 @@ zh-HK:
most_recent: 按時間
title: 排序
outbox_url: 寄件箱(Outbox)URL
- perform_full_suspension: 實行完全暫停
+ perform_full_suspension: 完全停權
profile_url: 個人檔案 URL
promote: 升任
protocol: 協議
@@ -272,6 +272,9 @@ zh-HK:
contact_information:
email: 輸入一個公開的電郵地址
username: 輸入用戶名稱
+ hero:
+ desc_html: 在首頁顯示。推薦最小 600x100px。如果留空,就會默認為服務站縮圖。
+ title: 主題圖片
peers_api_enabled:
desc_html: 現時本服務站在網絡中已發現的域名
title: 公開已知服務站的列表
@@ -288,6 +291,9 @@ zh-HK:
open:
desc_html: 允許所有人建立帳戶
title: 開放註冊
+ show_known_fediverse_at_about_page:
+ desc_html: 如果開啟,就會在時間軸預覽顯示跨站文章,否則就只會顯示本站文章。
+ title: 在時間軸預覽顯示跨站文章
show_staff_badge:
desc_html: 在個人資料頁上顯示管理人員標誌
title: 顯示管理人員標誌
@@ -352,6 +358,8 @@ zh-HK:
your_token: token
auth:
agreement_html: 登記即表示你同意遵守本服務站的規則和使用條款。
+ change_password: 密碼
+ confirm_email: 確認電郵
delete_account: 刪除帳戶
delete_account_html: 如果你想刪除你的帳戶,請點擊這裡繼續。你需要確認你的操作。
didnt_get_confirmation: 沒有收到確認指示電郵?
@@ -361,7 +369,13 @@ zh-HK:
logout: 登出
migrate_account: 轉移到另一個帳號
migrate_account_html: 想要將這個帳號指向另一個帳號可到這裡設定。
+ or: 或
+ or_log_in_with: 或登入於
+ providers:
+ cas: CAS
+ saml: SAML
register: 登記
+ register_elsewhere: 在其他服務站登記
resend_confirmation: 重發確認指示電郵
reset_password: 重設密碼
security: 登入資訊
@@ -411,6 +425,13 @@ zh-HK:
title: 這個頁面有問題
noscript_html: 使用 Mastodon 網頁版應用需要啟用 JavaScript。你也可以選擇適用於你的平台的 Mastodon 應用。
exports:
+ archive_takeout:
+ date: 日期
+ download: 下載檔案
+ hint_html: 你可以下載包含你的文章和媒體的檔案。資料以 ActivityPub 格式儲存,可用於相容的軟體。
+ in_progress: 檔案製作中...
+ request: 下載檔案
+ size: 檔案大小
blocks: 被你封鎖的用戶
csv: CSV
follows: 你所關注的用戶
@@ -524,7 +545,9 @@ zh-HK:
trillion: T
unit: ''
pagination:
+ newer: 較新
next: 下一頁
+ older: 較舊
prev: 上一頁
truncate: "……"
preferences:
@@ -606,6 +629,11 @@ zh-HK:
two_factor_authentication: 雙重認證
your_apps: 你的應用程式
statuses:
+ attached:
+ description: 附件: %{attached}
+ image: "%{count} 張圖片"
+ video: "%{count} 段影片"
+ content_warning: 'Content warning: %{warning}'
open_in_web: 開啟網頁
over_character_limit: 超過了 %{max} 字的限制
pin_errors:
@@ -670,4 +698,5 @@ zh-HK:
users:
invalid_email: 電郵地址格式不正確
invalid_otp_token: 雙重認證確認碼不正確
+ seamless_external_login: 由於你是從外部系統登入,所以不能設定密碼和電郵。
signed_in_as: 目前登入的帳戶:
From b04f73ce664b1f2c8f863b53ba8ff8fa0f0b330f Mon Sep 17 00:00:00 2001
From: Evgeny Petrov
Date: Mon, 2 Apr 2018 13:49:06 +0300
Subject: [PATCH 028/442] Russian language updated (#7005)
* Russian language updated
* Small fixes for RU language
* bundle exec i18n-tasks normalize
---
app/javascript/mastodon/locales/ru.json | 30 +++++++-------
config/locales/doorkeeper.ru.yml | 2 +-
config/locales/ru.yml | 54 ++++++++++++++++++++++---
config/locales/simple_form.ru.yml | 4 +-
4 files changed, 67 insertions(+), 23 deletions(-)
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 15959092c..8616ef98f 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -1,10 +1,10 @@
{
"account.block": "Блокировать",
"account.block_domain": "Блокировать все с {domain}",
- "account.blocked": "Blocked",
- "account.direct": "Direct Message @{name}",
+ "account.blocked": "Заблокирован(а)",
+ "account.direct": "Написать @{name}",
"account.disclaimer_full": "Нижеуказанная информация может не полностью отражать профиль пользователя.",
- "account.domain_blocked": "Domain hidden",
+ "account.domain_blocked": "Домен скрыт",
"account.edit_profile": "Изменить профиль",
"account.follow": "Подписаться",
"account.followers": "Подписаны",
@@ -16,9 +16,9 @@
"account.moved_to": "Ищите {name} здесь:",
"account.mute": "Заглушить",
"account.mute_notifications": "Скрыть уведомления от @{name}",
- "account.muted": "Muted",
+ "account.muted": "Приглушён",
"account.posts": "Посты",
- "account.posts_with_replies": "Toots with replies",
+ "account.posts_with_replies": "Посты с ответами",
"account.report": "Пожаловаться",
"account.requested": "Ожидает подтверждения",
"account.share": "Поделиться профилем @{name}",
@@ -29,8 +29,8 @@
"account.unmute": "Снять глушение",
"account.unmute_notifications": "Показывать уведомления от @{name}",
"account.view_full_profile": "Показать полный профиль",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "Что-то пошло не так.",
+ "alert.unexpected.title": "Ой!",
"boost_modal.combo": "Нажмите {combo}, чтобы пропустить это в следующий раз",
"bundle_column_error.body": "Что-то пошло не так при загрузке этого компонента.",
"bundle_column_error.retry": "Попробовать снова",
@@ -40,7 +40,7 @@
"bundle_modal_error.retry": "Попробовать снова",
"column.blocks": "Список блокировки",
"column.community": "Локальная лента",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "Скрытые домены",
"column.favourites": "Понравившееся",
"column.follow_requests": "Запросы на подписку",
"column.home": "Главная",
@@ -65,10 +65,10 @@
"compose_form.placeholder": "О чем Вы думаете?",
"compose_form.publish": "Трубить",
"compose_form.publish_loud": "{publish}!",
- "compose_form.sensitive.marked": "Media is marked as sensitive",
- "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
- "compose_form.spoiler.marked": "Text is hidden behind warning",
- "compose_form.spoiler.unmarked": "Text is not hidden",
+ "compose_form.sensitive.marked": "Медиафайлы не отмечены как чувствительные",
+ "compose_form.sensitive.unmarked": "Медиафайлы не отмечены как чувствительные",
+ "compose_form.spoiler.marked": "Текст скрыт за предупреждением",
+ "compose_form.spoiler.unmarked": "Текст не скрыт",
"compose_form.spoiler_placeholder": "Напишите свое предупреждение здесь",
"confirmation_modal.cancel": "Отмена",
"confirmations.block.confirm": "Заблокировать",
@@ -154,7 +154,7 @@
"mute_modal.hide_notifications": "Убрать уведомления от этого пользователя?",
"navigation_bar.blocks": "Список блокировки",
"navigation_bar.community_timeline": "Локальная лента",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "Скрытые домены",
"navigation_bar.edit_profile": "Изменить профиль",
"navigation_bar.favourites": "Понравившееся",
"navigation_bar.follow_requests": "Запросы на подписку",
@@ -221,13 +221,13 @@
"reply_indicator.cancel": "Отмена",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
- "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
+ "report.hint": "Жалоба будет отправлена модераторам Вашего сервера. Вы также можете указать подробную причину жалобы ниже:",
"report.placeholder": "Комментарий",
"report.submit": "Отправить",
"report.target": "Жалуемся на",
"search.placeholder": "Поиск",
"search_popout.search_format": "Продвинутый формат поиска",
- "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": "Возвращает посты, которые Вы написали, отметили как 'избранное', продвинули или в которых были упомянуты, а также содержащие юзернейм, имя и хэштеги.",
"search_popout.tips.hashtag": "хэштег",
"search_popout.tips.status": "статус",
"search_popout.tips.text": "Простой ввод текста покажет совпадающие имена пользователей, отображаемые имена и хэштеги",
diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml
index 05c3d971c..28c0ff0bd 100644
--- a/config/locales/doorkeeper.ru.yml
+++ b/config/locales/doorkeeper.ru.yml
@@ -39,7 +39,7 @@ ru:
callback_url: Callback URL
delete: Удалить
name: Название
- new: Новое Приложение
+ new: Новое приложение
scopes: Права
show: Показывать
title: Ваши приложения
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 81af42556..108ca33e9 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -48,7 +48,7 @@ ru:
reserved_username: Имя пользователя зарезервировано
roles:
admin: Администратор
- moderator: Мод
+ moderator: Модератор
unfollow: Отписаться
admin:
account_moderation_notes:
@@ -217,7 +217,7 @@ ru:
title: Снять блокировку с домена %{domain}
undo: Отменить
title: Доменные блокировки
- undo: Отемнить
+ undo: Отменить
email_domain_blocks:
add_new: Добавить новую
created_msg: Доменная блокировка еmail успешно создана
@@ -275,6 +275,9 @@ ru:
contact_information:
email: Введите публичный e-mail
username: Введите имя пользователя
+ hero:
+ desc_html: Отображается на главной странице. Рекомендуется разрешение не менее 600х100px. Если не установлено, используется изображение узла
+ title: Баннер узла
peers_api_enabled:
desc_html: Домены, которые были замечены этим узлом среди всей федерации
title: Публикация списка обнаруженных узлов
@@ -291,6 +294,9 @@ ru:
open:
desc_html: Позволяет любому создавать аккаунт
title: Открыть регистрацию
+ show_known_fediverse_at_about_page:
+ desc_html: Если включено, показывает посты со всех известных узлов в предпросмотре ленты. В противном случае отображаются только локальные посты.
+ title: Показывать известные узлы в предпросмотре ленты
show_staff_badge:
desc_html: Показывать метку персонала на странице пользователя
title: Показывать метку персонала
@@ -308,7 +314,7 @@ ru:
desc_html: Используется для предпросмотра с помощью OpenGraph и API. Рекомендуется разрешение 1200x630px
title: Картинка узла
timeline_preview:
- desc_html: Показывать публичную ленту на целевой странице
+ desc_html: Показывать публичную ленту на приветственной странице
title: Предпросмотр ленты
title: Настройки сайта
statuses:
@@ -368,13 +374,17 @@ ru:
migrate_account_html: Если Вы хотите перенести этот аккаунт на другой, вы можете сделать это здесь.
or: или
or_log_in_with: Или войти с помощью
+ providers:
+ cas: CAS
+ saml: SAML
register: Зарегистрироваться
- register_elsewhere: Зарегистрироваться на другом сервере
+ register_elsewhere: Зарегистрироваться на другом узле
resend_confirmation: Повторить отправку инструкции для подтверждения
reset_password: Сбросить пароль
- security: Изменить пароль
+ security: Безопасность
set_new_password: Задать новый пароль
authorize_follow:
+ already_following: Вы уже подписаны на этот аккаунт
error: К сожалению, при поиске удаленного аккаунта возникла ошибка
follow: Подписаться
follow_request: 'Вы отправили запрос на подписку:'
@@ -467,10 +477,13 @@ ru:
'21600': 6 часов
'3600': 1 час
'43200': 12 часов
+ '604800': 1 неделю
'86400': 1 день
expires_in_prompt: Никогда
generate: Сгенерировать
max_uses:
+ few: "%{count} исп."
+ many: "%{count} исп."
one: 1 исп.
other: "%{count} исп."
max_uses_prompt: Без лимита
@@ -514,11 +527,13 @@ ru:
favourite:
body: 'Ваш статус понравился %{name}:'
subject: "%{name} понравился Ваш статус"
+ title: Понравившийся статус
follow:
body: "%{name} теперь подписан(а) на Вас!"
subject: "%{name} теперь подписан(а) на Вас"
title: Новый подписчик
follow_request:
+ action: Управление запросами на подписку
body: "%{name} запросил Вас о подписке"
subject: "%{name} хочет подписаться на Вас"
title: Новый запрос о подписке
@@ -587,6 +602,7 @@ ru:
micro_messenger: MicroMessenger
nokia: Nokia S40 Ovi Browser
opera: Opera
+ otter: Otter
phantom_js: PhantomJS
qq: QQ Browser
safari: Safari
@@ -628,6 +644,19 @@ ru:
two_factor_authentication: Двухфакторная аутентификация
your_apps: Ваши приложения
statuses:
+ attached:
+ description: 'Вложение: %{attached}'
+ image:
+ few: "%{count} изображения"
+ many: "%{count} изображений"
+ one: "%{count} изображение"
+ other: "%{count} изображений"
+ video:
+ few: "%{count} видео"
+ many: "%{count} видео"
+ one: "%{count} видео"
+ other: "%{count} видео"
+ content_warning: 'Спойлер: %{warning}'
open_in_web: Открыть в WWW
over_character_limit: превышен лимит символов (%{max})
pin_errors:
@@ -636,6 +665,7 @@ ru:
private: Нельзя закрепить непубличный статус
reblog: Нельзя закрепить продвинутый статус
show_more: Подробнее
+ title: '%{name}: "%{quote}"'
visibilities:
private: Для подписчиков
private_long: Показывать только подписчикам
@@ -717,12 +747,24 @@ ru:
title: Вынос архива
welcome:
edit_profile_action: Настроить профиль
+ edit_profile_step: Вы можете настроить свой профиль, загрузив аватар, обложку, сменив имя и много чего ещё. Если Вы хотите фильтровать подписчиков до того, как они смогут на Вас подписаться, Вы можете закрыть свой аккаунт.
+ explanation: Несколько советов для новичков
final_action: Начать постить
+ final_step: 'Начните постить! Ваши публичные посты могут видеть другие, например, в локальной ленте или по хэштегам, даже если у Вас нет подписчиков. Вы также можете поздороваться с остальными и представиться, используя хэштек #приветствие.'
+ full_handle: Ваше обращение
+ full_handle_hint: То, что Вы хотите сообщить своим друзьям, чтобы они могли написать Вам или подписаться с другого узла.
review_preferences_action: Изменить настройки
- subject: Добро пожаловать на Mastodon
+ review_preferences_step: Проверьте все настройки, например, какие письма Вы хотите получать или уровень приватности статусов по умолчанию. Если Вы не страдаете морской болезнь, можете включить автовоспроизведение GIF.
+ subject: Добро пожаловать в Mastodon
+ tip_bridge_html: Если Вы пришли из Twitter, можете поискать своих друзей в Mastodon, используя приложение-мост. Но это работает только если они тоже использовали это приложение!
+ tip_federated_timeline: В глобальной ленте отображается сеть Mastodon. Но в ней показаны посты только от людей, на которых подписаны Вы и Ваши соседи, поэтому лента может быть неполной.
+ tip_following: По умолчанию Вы подписаны на администратора(-ов) Вашего узла. Чтобы найти других интересных людей, проверьте локальную и глобальную ленты.
+ tip_local_timeline: В локальной ленте показаны посты от людей с %{instance}. Это Ваши непосредственные соседи!
+ tip_mobile_webapp: Если Ваш мобильный браузер предлагает добавить иконку Mastodon на домашний экран, то Вы можете получать push-уведомления. Прямо как полноценное приложение!
tips: Советы
title: Добро пожаловать на борт, %{name}!
users:
invalid_email: Введенный e-mail неверен
invalid_otp_token: Введен неверный код
+ seamless_external_login: Вы залогинены через сторонний сервис, поэтому настройки e-mail и пароля недоступны.
signed_in_as: 'Выполнен вход под именем:'
diff --git a/config/locales/simple_form.ru.yml b/config/locales/simple_form.ru.yml
index 5c4df2189..b8ee5892d 100644
--- a/config/locales/simple_form.ru.yml
+++ b/config/locales/simple_form.ru.yml
@@ -38,7 +38,7 @@ ru:
filtered_languages: Фильтруемые языки
header: Заголовок
locale: Язык
- locked: Сделать аккаунт приватным
+ locked: Сделать аккаунт закрытым
max_uses: Макс. число использований
new_password: Новый пароль
note: О Вас
@@ -49,6 +49,7 @@ ru:
setting_default_privacy: Видимость постов
setting_default_sensitive: Всегда отмечать медиаконтент как чувствительный
setting_delete_modal: Показывать диалог подтверждения перед удалением
+ setting_display_sensitive_media: Всегда показывать медиаконтент, отмеченный как чувствительный
setting_noindex: Отказаться от индексации в поисковых машинах
setting_reduce_motion: Уменьшить движение в анимации
setting_system_font_ui: Использовать шрифт системы по умолчанию
@@ -57,6 +58,7 @@ ru:
severity: Строгость
type: Тип импорта
username: Имя пользователя
+ username_or_email: Имя пользователя или e-mail
interactions:
must_be_follower: Заблокировать уведомления не от подписчиков
must_be_following: Заблокировать уведомления от людей, на которых Вы не подписаны
From 3f51c6efaac0a0705d363e021951b0dd6b071a28 Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Mon, 2 Apr 2018 20:43:30 +0900
Subject: [PATCH 029/442] Weblate translations (2018-04-02) (#7007)
* Translated using Weblate (Galician)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ca/
* Translated using Weblate (Arabic)
Currently translated at 76.4% (449 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Slovak)
Currently translated at 92.3% (542 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 92.3% (542 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/sk/
* Translated using Weblate (Polish)
Currently translated at 98.9% (581 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pl/
* Translated using Weblate (French)
Currently translated at 99.6% (585 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/
* Translated using Weblate (Persian)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/fa/
* Translated using Weblate (Persian)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fa/
* Translated using Weblate (French)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/zh_Hant/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/zh_Hant/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/zh_Hant/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/zh_Hant/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eo/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/zh_Hant/
* Translated using Weblate (Arabic)
Currently translated at 76.6% (450 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eo/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Slovak)
Currently translated at 92.6% (544 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/sk/
* Translated using Weblate (Arabic)
Currently translated at 82.9% (487 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Arabic)
Currently translated at 98.6% (74 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/ar/
* Translated using Weblate (Slovak)
Currently translated at 93.6% (550 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 95.4% (560 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Japanese)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/
* Translated using Weblate (Indonesian)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/id/
* Translated using Weblate (Korean)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ko/
* Translated using Weblate (Korean)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ko/
* Translated using Weblate (Korean)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ko/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Arabic)
Currently translated at 82.9% (487 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Arabic)
Currently translated at 99.2% (278 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/
* Translated using Weblate (Arabic)
Currently translated at 87.3% (513 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Arabic)
Currently translated at 99.6% (279 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/
* bundle exec i18n-tasks normalize && yarn manage:translations
* revert
---
app/javascript/mastodon/locales/ar.json | 6 +-
app/javascript/mastodon/locales/ca.json | 2 +-
app/javascript/mastodon/locales/eo.json | 18 ++---
app/javascript/mastodon/locales/fa.json | 10 +--
app/javascript/mastodon/locales/fr.json | 42 ++++++------
app/javascript/mastodon/locales/ja.json | 2 +-
app/javascript/mastodon/locales/ko.json | 4 +-
app/javascript/mastodon/locales/sk.json | 8 +--
app/javascript/mastodon/locales/zh-TW.json | 4 +-
config/locales/ar.yml | 79 +++++++++++++++++++++-
config/locales/devise.zh-TW.yml | 25 ++++++-
config/locales/doorkeeper.ar.yml | 5 ++
config/locales/doorkeeper.fa.yml | 16 ++---
config/locales/doorkeeper.id.yml | 4 ++
config/locales/doorkeeper.sk.yml | 4 +-
config/locales/doorkeeper.zh-TW.yml | 14 ++--
config/locales/eo.yml | 13 +++-
config/locales/ja.yml | 4 +-
config/locales/ko.yml | 16 +++++
config/locales/simple_form.ko.yml | 2 +
config/locales/sk.yml | 24 +++++++
21 files changed, 233 insertions(+), 69 deletions(-)
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 3078b5b8c..34e34411f 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -2,7 +2,7 @@
"account.block": "حظر @{name}",
"account.block_domain": "إخفاء كل شيئ قادم من إسم النطاق {domain}",
"account.blocked": "محظور",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "قد لا تعكس المعلومات أدناه الملف الشخصي الكامل للمستخدم.",
"account.domain_blocked": "النطاق مخفي",
"account.edit_profile": "تعديل الملف الشخصي",
@@ -66,7 +66,7 @@
"compose_form.publish": "بوّق",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "لقد تم تحديد هذه الصورة كحساسة",
- "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
+ "compose_form.sensitive.unmarked": "لم يتم تحديد الصورة كحساسة",
"compose_form.spoiler.marked": "إنّ النص مخفي وراء تحذير",
"compose_form.spoiler.unmarked": "النص غير مخفي",
"compose_form.spoiler_placeholder": "تنبيه عن المحتوى",
@@ -221,7 +221,7 @@
"reply_indicator.cancel": "إلغاء",
"report.forward": "التحويل إلى {target}",
"report.forward_hint": "هذا الحساب ينتمي إلى خادوم آخَر. هل تودّ إرسال نسخة مجهولة مِن التقرير إلى هنالك أيضًا ؟",
- "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
+ "report.hint": "سوف يتم إرسال التقرير إلى مُشرِفي مثيل خادومكم. بإمكانك الإدلاء بشرح عن سبب الإبلاغ عن الحساب أسفله :",
"report.placeholder": "تعليقات إضافية",
"report.submit": "إرسال",
"report.target": "إبلاغ",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index ec5a8a1d6..b7f95a664 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -2,7 +2,7 @@
"account.block": "Bloca @{name}",
"account.block_domain": "Amaga-ho tot de {domain}",
"account.blocked": "Bloquejat",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.",
"account.domain_blocked": "Domini ocult",
"account.edit_profile": "Edita el perfil",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 82b749417..6dee6e544 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": "Direct message @{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",
@@ -17,8 +17,8 @@
"account.mute": "Silentigi @{name}",
"account.mute_notifications": "Silentigi sciigojn el @{name}",
"account.muted": "Silentigita",
- "account.posts": "Mesaĝoj",
- "account.posts_with_replies": "Mesaĝoj kun respondoj",
+ "account.posts": "Tootoj",
+ "account.posts_with_replies": "Kun respondoj",
"account.report": "Signali @{name}",
"account.requested": "Atendo de aprobo. Alklaku por nuligi peton de sekvado",
"account.share": "Diskonigi la profilon de @{name}",
@@ -65,10 +65,10 @@
"compose_form.placeholder": "Pri kio vi pensas?",
"compose_form.publish": "Hup",
"compose_form.publish_loud": "{publish}!",
- "compose_form.sensitive.marked": "Media is marked as sensitive",
- "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
- "compose_form.spoiler.marked": "Text is hidden behind warning",
- "compose_form.spoiler.unmarked": "Text is not hidden",
+ "compose_form.sensitive.marked": "Aŭdovidaĵo markita tikla",
+ "compose_form.sensitive.unmarked": "Aŭdovidaĵo ne markita tikla",
+ "compose_form.spoiler.marked": "Teksto kaŝita malantaŭ averto",
+ "compose_form.spoiler.unmarked": "Teksto ne kaŝita",
"compose_form.spoiler_placeholder": "Skribu vian averton ĉi tie",
"confirmation_modal.cancel": "Nuligi",
"confirmations.block.confirm": "Bloki",
@@ -260,9 +260,9 @@
"status.sensitive_warning": "Tikla enhavo",
"status.share": "Diskonigi",
"status.show_less": "Malgrandigi",
- "status.show_less_all": "Show less for all",
+ "status.show_less_all": "Malgrandigi ĉiujn",
"status.show_more": "Grandigi",
- "status.show_more_all": "Show more for all",
+ "status.show_more_all": "Grandigi ĉiujn",
"status.unmute_conversation": "Malsilentigi konversacion",
"status.unpin": "Depingli de profilo",
"tabs_bar.federated_timeline": "Fratara tempolinio",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 4b64ca353..61cdcd00a 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -1,10 +1,10 @@
{
"account.block": "مسدودسازی @{name}",
"account.block_domain": "پنهانسازی همه چیز از سرور {domain}",
- "account.blocked": "Blocked",
- "account.direct": "Direct Message @{name}",
+ "account.blocked": "مسدودشده",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "اطلاعات زیر ممکن است نمایهٔ این کاربر را به تمامی نشان ندهد.",
- "account.domain_blocked": "Domain hidden",
+ "account.domain_blocked": "دامین پنهانشده",
"account.edit_profile": "ویرایش نمایه",
"account.follow": "پی بگیرید",
"account.followers": "پیگیران",
@@ -16,9 +16,9 @@
"account.moved_to": "{name} منتقل شده است به:",
"account.mute": "بیصدا کردن @{name}",
"account.mute_notifications": "بیصداکردن اعلانها از طرف @{name}",
- "account.muted": "Muted",
+ "account.muted": "بیصداشده",
"account.posts": "نوشتهها",
- "account.posts_with_replies": "Toots with replies",
+ "account.posts_with_replies": "نوشتهها و پاسخها",
"account.report": "گزارش @{name}",
"account.requested": "در انتظار پذیرش",
"account.share": "همرسانی نمایهٔ @{name}",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 58e6ad54d..57c55c9bd 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -2,7 +2,7 @@
"account.block": "Bloquer @{name}",
"account.block_domain": "Tout masquer venant de {domain}",
"account.blocked": "Bloqué",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "Les données ci-dessous peuvent ne pas refléter ce profil dans sa totalité.",
"account.domain_blocked": "Domaine caché",
"account.edit_profile": "Modifier le profil",
@@ -20,7 +20,7 @@
"account.posts": "Pouets",
"account.posts_with_replies": "Pouets avec réponses",
"account.report": "Signaler",
- "account.requested": "Invitation envoyée",
+ "account.requested": "En attente d'approbation. Cliquez pour annuler la requête",
"account.share": "Partager le profil de @{name}",
"account.show_reblogs": "Afficher les partages de @{name}",
"account.unblock": "Débloquer",
@@ -88,7 +88,7 @@
"emoji_button.activity": "Activités",
"emoji_button.custom": "Personnalisés",
"emoji_button.flags": "Drapeaux",
- "emoji_button.food": "Boire et manger",
+ "emoji_button.food": "Nourriture & Boisson",
"emoji_button.label": "Insérer un émoji",
"emoji_button.nature": "Nature",
"emoji_button.not_found": "Pas d'emojis !! (╯°□°)╯︵ ┻━┻",
@@ -98,14 +98,14 @@
"emoji_button.search": "Recherche…",
"emoji_button.search_results": "Résultats de la recherche",
"emoji_button.symbols": "Symboles",
- "emoji_button.travel": "Lieux et voyages",
+ "emoji_button.travel": "Lieux & Voyages",
"empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir !",
"empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag.",
- "empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres utilisateur⋅ice⋅s.",
+ "empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres personnes.",
"empty_column.home.public_timeline": "le fil public",
"empty_column.list": "Il n'y a rien dans cette liste pour l'instant. Dès que des personnes de cette liste publierons de nouveaux statuts, ils apparaîtront ici.",
- "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres utilisateur⋅ice⋅s pour débuter la conversation.",
- "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des utilisateur⋅ice·s d’autres instances pour remplir le fil public",
+ "empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres personnes pour débuter la conversation.",
+ "empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des personnes d’autres instances pour remplir le fil public",
"follow_request.authorize": "Accepter",
"follow_request.reject": "Rejeter",
"getting_started.appsshort": "Applications",
@@ -122,9 +122,9 @@
"keyboard_shortcuts.back": "revenir en arrière",
"keyboard_shortcuts.boost": "partager",
"keyboard_shortcuts.column": "focaliser un statut dans l'une des colonnes",
- "keyboard_shortcuts.compose": "pour centrer la zone de redaction",
+ "keyboard_shortcuts.compose": "pour centrer la zone de rédaction",
"keyboard_shortcuts.description": "Description",
- "keyboard_shortcuts.down": "descendre dans la liste",
+ "keyboard_shortcuts.down": "pour descendre dans la liste",
"keyboard_shortcuts.enter": "pour ouvrir le statut",
"keyboard_shortcuts.favourite": "vers les favoris",
"keyboard_shortcuts.heading": "Raccourcis clavier",
@@ -151,7 +151,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 cet utilisateur ?",
+ "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.domain_blocks": "Hidden domains",
@@ -170,7 +170,7 @@
"notification.follow": "{name} vous suit",
"notification.mention": "{name} vous a mentionné⋅e :",
"notification.reblog": "{name} a partagé votre statut :",
- "notifications.clear": "Nettoyer",
+ "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 :",
@@ -183,12 +183,12 @@
"notifications.column_settings.sound": "Émettre un son",
"onboarding.done": "Effectué",
"onboarding.next": "Suivant",
- "onboarding.page_five.public_timelines": "Le fil public global affiche les posts de tou⋅te⋅s les utilisateur⋅ice⋅s suivi⋅es par les membres de {domain}. Le fil public local est identique mais se limite aux utilisateur⋅ice⋅s de {domain}.",
- "onboarding.page_four.home": "L’Accueil affiche les posts de tou⋅te·s les utilisateur⋅ice·s que vous suivez.",
- "onboarding.page_four.notifications": "Les Notifications vous informent lorsque quelqu’un interagit avec vous.",
- "onboarding.page_one.federation": "Mastodon est un réseau social qui appartient à tou⋅te⋅s.",
- "onboarding.page_one.full_handle": "Votre pleine maîtrise",
- "onboarding.page_one.handle_hint": "C'est ce que vous diriez à vos amis de rechercher.",
+ "onboarding.page_five.public_timelines": "Le fil public global affiche les messages de toutes les personnes suivies par les membres de {domain}. Le fil public local est identique mais se limite aux membres de {domain}.",
+ "onboarding.page_four.home": "L’Accueil affiche les messages des personnes que vous suivez.",
+ "onboarding.page_four.notifications": "La colonne de notification vous avertit lors d'une interaction avec vous.",
+ "onboarding.page_one.federation": "Mastodon est un réseau de serveurs indépendants qui se joignent pour former un réseau social plus vaste. Nous appelons ces serveurs des instances.",
+ "onboarding.page_one.full_handle": "Votre identifiant complet",
+ "onboarding.page_one.handle_hint": "C'est ce que vos amis devront rechercher.",
"onboarding.page_one.welcome": "Bienvenue sur Mastodon !",
"onboarding.page_six.admin": "L’administrateur⋅ice de votre instance est {admin}.",
"onboarding.page_six.almost_done": "Nous y sommes presque…",
@@ -199,7 +199,7 @@
"onboarding.page_six.read_guidelines": "S’il vous plaît, n’oubliez pas de lire les {guidelines} !",
"onboarding.page_six.various_app": "applications mobiles",
"onboarding.page_three.profile": "Modifiez votre profil pour changer votre avatar, votre description ainsi que votre nom. Vous y trouverez également d’autres préférences.",
- "onboarding.page_three.search": "Utilisez la barre de recherche pour trouver des utilisateur⋅ice⋅s et regarder des hashtags tels que {illustration} et {introductions}. Pour trouver quelqu’un qui n’est pas sur cette instance, utilisez son nom d’utilisateur⋅ice complet.",
+ "onboarding.page_three.search": "Utilisez la barre de recherche pour trouver des utilisateur⋅ice⋅s ou regardez des hashtags tels que {illustration} et {introductions}. Pour trouver quelqu’un qui n’est pas sur cette instance, utilisez son identifiant complet.",
"onboarding.page_two.compose": "Écrivez depuis la colonne de composition. Vous pouvez ajouter des images, changer les réglages de confidentialité, et ajouter des avertissements de contenu (Content Warning) grâce aux icônes en dessous.",
"onboarding.skip": "Passer",
"privacy.change": "Ajuster la confidentialité du message",
@@ -227,16 +227,16 @@
"report.target": "Signalement",
"search.placeholder": "Rechercher",
"search_popout.search_format": "Recherche avancée",
- "search_popout.tips.full_text": "Les textes simples retournent les pouets que vous avez écris, mis en favori, épinglés, ou ayant été mentionnés, ainsi que les noms d'utilisateurs, les noms affichés, et les hashtags correspondant.",
+ "search_popout.tips.full_text": "Les textes simples retournent les pouets que vous avez écris, mis en favori, épinglés, ou ayant été mentionnés, ainsi que les identifiants, les noms affichés, et les hashtags des personnes et messages correspondant.",
"search_popout.tips.hashtag": "hashtag",
"search_popout.tips.status": "statuts",
- "search_popout.tips.text": "Un texte simple renvoie les noms affichés, les noms d’utilisateur⋅ice et les hashtags correspondants",
+ "search_popout.tips.text": "Un texte simple renvoie les noms affichés, les identifiants et les hashtags correspondants",
"search_popout.tips.user": "utilisateur⋅ice",
"search_results.accounts": "Personnes",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Pouets",
"search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}",
- "standalone.public_title": "Jeter un coup d’œil…",
+ "standalone.public_title": "Un aperçu …",
"status.block": "Block @{name}",
"status.cannot_reblog": "Cette publication ne peut être boostée",
"status.delete": "Effacer",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 80a13a9bf..432517716 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -27,7 +27,7 @@
"account.unblock_domain": "{domain}を表示",
"account.unfollow": "フォロー解除",
"account.unmute": "@{name}さんのミュートを解除",
- "account.unmute_notifications": "@{name}さんからの通知を受け取る",
+ "account.unmute_notifications": "@{name}さんからの通知を受け取るようにする",
"account.view_full_profile": "全ての情報を見る",
"alert.unexpected.message": "不明なエラーが発生しました",
"alert.unexpected.title": "エラー",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 449df42b8..89fde8966 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -2,7 +2,7 @@
"account.block": "@{name}을 차단",
"account.block_domain": "{domain} 전체를 숨김",
"account.blocked": "차단 됨",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "여기 있는 정보는 유저의 프로파일을 정확히 반영하지 못 할 수도 있습니다.",
"account.domain_blocked": "도메인 숨겨짐",
"account.edit_profile": "프로필 편집",
@@ -17,7 +17,7 @@
"account.mute": "@{name} 뮤트",
"account.mute_notifications": "@{name}의 알림을 뮤트",
"account.muted": "뮤트 됨",
- "account.posts": "게시물",
+ "account.posts": "툿",
"account.posts_with_replies": "툿과 답장",
"account.report": "@{name} 신고",
"account.requested": "승인 대기 중. 클릭해서 취소하기",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 7bfae0302..925b46df6 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -2,7 +2,7 @@
"account.block": "Blokovať @{name}",
"account.block_domain": "Ukryť všetko z {domain}",
"account.blocked": "Blokovaný/á",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "Inofrmácie nižšie nemusia byť úplným odrazom uživateľovho účtu.",
"account.domain_blocked": "Doména ukrytá",
"account.edit_profile": "Upraviť profil",
@@ -42,12 +42,12 @@
"column.community": "Lokálna časová os",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Obľúbené",
- "column.follow_requests": "Žiadosti o sledovaní",
+ "column.follow_requests": "Žiadosti o sledovanie",
"column.home": "Domov",
"column.lists": "Zoznamy",
"column.mutes": "Ignorovaní užívatelia",
"column.notifications": "Notifikácie",
- "column.pins": "Pripnuté toots",
+ "column.pins": "Pripnuté tooty",
"column.public": "Federovaná časová os",
"column_back_button.label": "Späť",
"column_header.hide_settings": "Skryť nastavenia",
@@ -163,7 +163,7 @@
"navigation_bar.lists": "Zoznamy",
"navigation_bar.logout": "Odhlásiť",
"navigation_bar.mutes": "Ignorovaní užívatelia",
- "navigation_bar.pins": "Pripnuté toots",
+ "navigation_bar.pins": "Pripnuté tooty",
"navigation_bar.preferences": "Voľby",
"navigation_bar.public_timeline": "Federovaná časová os",
"notification.favourite": "{name} sa páči tvoj status",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index fab7ecf06..c7925829f 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -2,7 +2,7 @@
"account.block": "封鎖 @{name}",
"account.block_domain": "隱藏來自 {domain} 的一切貼文",
"account.blocked": "Blocked",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "下列資料不一定完整。",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "編輯用者資訊",
@@ -103,7 +103,7 @@
"empty_column.hashtag": "這個主題標籤下什麼都沒有。",
"empty_column.home": "你還沒關注任何人。造訪{public}或利用搜尋功能找到其他用者。",
"empty_column.home.public_timeline": "公開時間軸",
- "empty_column.list": "There is nothing in this list yet.",
+ "empty_column.list": "此份清單尚未有東西。當此清單的成員貼出了新的狀態時,它們就會出現在這裡。",
"empty_column.notifications": "還沒有任何通知。和別的使用者互動來開始對話。",
"empty_column.public": "這裡什麼都沒有!公開寫些什麼,或是關注其他副本的使用者。",
"follow_request.authorize": "授權",
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index 25ca302d6..c316a2fa5 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -119,6 +119,7 @@ ar:
user: مستخدِم
salmon_url: عنوان رابط سالمون Salmon
search: البحث
+ shared_inbox_url: رابط الصندوق المُشترَك للبريد الوارد
show:
created_reports: البلاغات التي أنشأها هذا الحساب
report: التقرير
@@ -140,14 +141,23 @@ ar:
create_email_domain_block: "%{name} قد قام بحظر نطاق البريد الإلكتروني %{target}"
demote_user: "%{name} قد قام بإنزال الرتبة الوظيفية لـ %{target}"
destroy_domain_block: "%{name} قام بإلغاء الحجب عن النطاق %{target}"
+ destroy_email_domain_block: قام %{name} بإضافة نطاق البريد الإلكتروني %{target} إلى اللائحة البيضاء
+ destroy_status: لقد قام %{name} بحذف منشور %{target}
disable_2fa_user: "%{name} لقد قام بتعطيل ميزة المصادقة بخطوتين للمستخدم %{target}"
disable_custom_emoji: "%{name} قام بتعطيل الإيموجي %{target}"
disable_user: "%{name} لقد قام بتعطيل تسجيل الدخول للمستخدِم %{target}"
enable_custom_emoji: "%{name} قام بتنشيط الإيموجي %{target}"
enable_user: "%{name} لقد قام بتنشيط تسجيل الدخول للمستخدِم %{target}"
+ memorialize_account: لقد قام %{name} بتحويل حساب %{target} إلى صفحة تذكارية
promote_user: "%{name} قام بترقية المستخدم %{target}"
reset_password_user: "%{name} لقد قام بإعادة تعيين الكلمة السرية الخاصة بـ %{target}"
+ resolve_report: قام %{name} بإلغاء التقرير المُرسَل مِن طرف %{target}
+ silence_account: لقد قام %{name} بكتم حساب %{target}
+ suspend_account: لقد قام %{name} بتعليق حساب %{target}
+ unsilence_account: لقد قام %{name} بإلغاء الكتم عن حساب %{target}
+ unsuspend_account: لقد قام %{name} بإلغاء التعليق المفروض على حساب %{target}
update_custom_emoji: "%{name} قام بتحديث الإيموجي %{target}"
+ update_status: لقد قام %{name} بتحديث منشور %{target}
title: سِجلّ التفتيش و المعاينة
custom_emojis:
by_domain: النطاق
@@ -163,35 +173,54 @@ ar:
enable: تفعيل
enabled_msg: تم تنشيط ذاك الإيموجي بنجاح
image_hint: ملف PNG إلى غاية حجم 50 ك.ب
+ listed: مُدرَج
new:
title: إضافة إيموجي خاص جديد
+ overwrite: إعادة الكتابة
shortcode: الترميز المُصَغّر
shortcode_hint: على الأقل حرفين، و فقط رموز أبجدية عددية و أسطر سفلية
title: الإيموجي الخاصة
+ unlisted: غير مدرج
update_failed_msg: تعذرت عملية تحذيث ذاك الإيموجي
updated_msg: تم تحديث الإيموجي بنجاح !
upload: رفع
domain_blocks:
add_new: إضافة نطاق جديد
+ created_msg: إنّ حجب النطاق حيز التشغيل
+ destroyed_msg: تم إلغاء الحجب المفروض على النطاق
domain: النطاق
new:
create: إنشاء حظر
severity:
noop: لا شيء
silence: كتم
+ suspend: تعليق
title: حجب نطاق جديد
reject_media: رفض ملفات الوسائط
severities:
noop: لا شيء
+ silence: إخفاء أو كتم
+ suspend: تعليق
+ severity: الشدة
show:
+ affected_accounts:
+ other: هناك %{count} حسابات في قاعدة البيانات متأثرة بذلك
+ retroactive:
+ silence: إلغاء الكتم عن كافة الحسابات المتواجدة على هذا النطاق
+ suspend: إلغاء التعليق المفروض على كافة حسابات هذا النطاق
title: رفع حظر النطاق عن %{domain}
undo: إلغاء
+ title: حظر النطاقات
undo: إلغاء
email_domain_blocks:
+ add_new: إضافة
+ created_msg: لقد دخل حظر نطاق البريد الإلكتروني حيّز الخدمة
delete: حذف
+ destroyed_msg: تم حذف نطاق البريد الإلكتروني من اللائحة السوداء بنجاح
domain: النطاق
new:
create: إضافة نطاق
+ title: إضافة نطاق بريد جديد إلى اللائحة السوداء
title: القائمة السوداء للبريد الإلكتروني
instances:
account_count: الحسابات المعروفة
@@ -214,27 +243,52 @@ ar:
none: لا شيء
delete: حذف
id: معرّف ID
+ mark_as_resolved: إعتبار التقرير كمحلول
nsfw:
+ 'false': الكشف عن الصور
'true': إخفاء الوسائط المرفقة
+ report: 'التقرير #%{id}'
report_contents: المحتويات
+ reported_account: حساب مُبلّغ عنه
reported_by: أبلغ عنه من طرف
+ resolved: معالجة
+ silence_account: كتم و إخفاء الحساب
status: الحالة
+ suspend_account: فرض تعليق على الحساب
+ target: الهدف
title: التقارير
+ unresolved: غير معالجة
view: عرض
settings:
+ activity_api_enabled:
+ desc_html: عدد المنشورات المحلية و المستخدمين النشطين و التسجيلات الأسبوعية الجديدة
+ bootstrap_timeline_accounts:
+ title: الإشتراكات الإفتراضية للمستخدمين الجدد
contact_information:
email: البريد الإلكتروني المهني
username: الإتصال بالمستخدِم
+ hero:
+ title: الصورة الرأسية
+ peers_api_enabled:
+ desc_html: أسماء النطاقات التي إلتقى بها مثيل الخادوم على البيئة الموحَّدة فيديفرس
+ title: نشر عدد مثيلات الخوادم التي تم مصادفتها
registrations:
closed_message:
title: رسالة التسجيلات المقفلة
deletion:
desc_html: السماح لأي مستخدم إغلاق حسابه
+ title: السماح بحذف الحسابات
+ min_invite_role:
+ disabled: لا أحد
open:
desc_html: السماح للجميع بإنشاء حساب
title: فتح التسجيل
+ show_known_fediverse_at_about_page:
+ title: إظهار الفيديفرس الموحَّد في خيط المُعايَنة
site_description:
title: وصف مثيل الخادوم
+ site_description_extended:
+ title: الوصف المُفصّل للموقع
site_terms:
title: شروط الخدمة المخصصة
site_title: إسم مثيل الخادم
@@ -242,11 +296,14 @@ ar:
title: الصورة الرمزية المصغرة لمثيل الخادوم
timeline_preview:
desc_html: عرض الخيط العمومي على صفحة الإستقبال
+ title: مُعاينة الخيط العام
title: إعدادات الموقع
statuses:
back_to_account: العودة إلى صفحة الحساب
batch:
delete: حذف
+ execute: تفعيل
+ failed_to_execute: خطأ في التفعيل
media:
hide: إخفاء الوسائط
show: إظهار الوسائط
@@ -256,8 +313,13 @@ ar:
subscriptions:
confirmed: مؤكَّد
expires_in: تنتهي مدة صلاحيتها في
+ last_delivery: آخر إيداع
+ title: WebSub
topic: الموضوع
title: الإدارة
+ admin_mailer:
+ new_report:
+ body: قام %{reporter} بالإبلاغ عن %{target}
application_mailer:
notification_preferences: تعديل خيارات البريد الإلكتروني
salutation: "%{name}،"
@@ -270,6 +332,7 @@ ar:
destroyed: تم حذف التطبيق بنجاح
invalid_url: إن الرابط المقدم غير صالح
regenerate_token: إعادة توليد رمز النفاذ
+ warning: كن حذرا مع هذه البيانات. لا تقم أبدا بمشاركتها مع الآخَرين !
your_token: رمز نفاذك
auth:
agreement_html: بقبولك التسجيل فإنك تُصرِّح قبول قواعد مثيل الخادوم و شروط الخدمة التي نوفرها لك.
@@ -283,11 +346,13 @@ ar:
logout: خروج
migrate_account: الإنتقال إلى حساب آخر
migrate_account_html: إن كنت ترغب في تحويل هذا الحساب نحو حساب آخَر، يُمكِنُك إعداده هنا.
+ or: أو
or_log_in_with: أو قم بتسجيل الدخول بواسطة
providers:
cas: CAS
saml: SAML
register: إنشاء حساب
+ register_elsewhere: التسجيل على خادوم آخَر
resend_confirmation: إعادة إرسال تعليمات التأكيد
reset_password: إعادة تعيين كلمة المرور
security: الهوية
@@ -296,6 +361,7 @@ ar:
error: يا للأسف، وقع هناك خطأ إثر عملية البحث عن الحساب عن بعد
follow: إتبع
follow_request: 'لقد قمت بإرسال طلب متابعة إلى :'
+ following: 'مرحى ! أنت الآن تتبع :'
post_follow:
close: أو يمكنك إغلاق هذه النافذة.
return: العودة إلى الملف الشخصي للمستخدم
@@ -324,18 +390,24 @@ ar:
'403': ليس لك الصلاحيات الكافية لعرض هذه الصفحة.
'404': إنّ الصفحة التي تبحث عنها لا وجود لها أصلا.
'410': إنّ الصفحة التي تبحث عنها لم تعد موجودة.
+ '422':
+ content: فشل التحقق الآمن. ربما منعتَ كعكات الكوكيز ؟
+ title: فشِل التحقق الآمن
'500':
content: نحن متأسفون، لقد حدث خطأ ما مِن جانبنا.
title: هذه الصفحة خاطئة
exports:
archive_takeout:
+ date: التاريخ
download: تنزيل نسخة لحسابك
hint_html: بإمكانك طلب نسخة كاملة لـ كافة تبويقاتك و الوسائط التي قمت بنشرها. البيانات المُصدَّرة ستكون محفوظة على شكل نسق ActivityPub و باستطاعتك قراءتها بأي برنامج يدعم هذا النسق.
in_progress: عملية جمع نسخة لبيانات حسابك جارية …
request: طلب نسخة لحسابك
+ size: الحجم
blocks: قمت بحظر
csv: CSV
follows: أنت تتبع
+ mutes: قُمتَ بكتم
storage: ذاكرة التخزين
followers:
domain: النطاق
@@ -368,9 +440,14 @@ ar:
'86400': يوم واحد
expires_in_prompt: أبدا
generate: توليد
+ max_uses:
+ one: إستعمال واحد
+ other: "%{count} استخدامات"
max_uses_prompt: بلا حدود
+ prompt: توليد و مشاركة روابط للسماح للآخَرين بالنفاذ إلى مثيل الخادوم هذا
table:
expires_at: تنتهي مدة صلاحيتها في
+ uses: يستخدِم
title: دعوة أشخاص
landing_strip_html: "%{name} هو أحد مُستخدِمي %{link_to_root_path}. بإمكانك متابعته أو التواصل معه إن كنت تملك حسابًا أيا كان على البيئة الموحَّدة فيديفرس."
landing_strip_signup_html: إن كنت لا تملك واحدا، يمكنك التسجيل مِن هنا.
@@ -433,7 +510,7 @@ ar:
next: التالي
older: الأقدَم
prev: السابق
- truncate: "…"
+ truncate: و
preferences:
languages: اللغات
other: إعدادات أخرى
diff --git a/config/locales/devise.zh-TW.yml b/config/locales/devise.zh-TW.yml
index e627653f1..976e96be2 100644
--- a/config/locales/devise.zh-TW.yml
+++ b/config/locales/devise.zh-TW.yml
@@ -2,7 +2,7 @@
zh-TW:
devise:
confirmations:
- confirmed: 信箱驗證成功
+ confirmed: 您的電子郵件地址確認成功。
send_instructions: 您將會在幾分鐘內收到驗證信。
send_paranoid_instructions: 如果您的電子信箱已經存在於我們的資料庫,您將會在幾分鐘內收到信,確認您電子信箱的指示。
failure:
@@ -10,18 +10,39 @@ zh-TW:
inactive: 您的帳號尚未啟用。
invalid: 不正確的 %{authentication_keys} 或密碼。
last_attempt: 若您再次嘗試失敗,我們將鎖定您的帳號,以策安全。
- locked: 您的帳號已被鎖定
+ locked: 您的帳號已被鎖定。
not_found_in_database: 不正確的 %{authentication_keys} 或密碼。
timeout: 您的登入階段已經逾期,請重新登入以繼續使用。
unauthenticated: 您必須先登入或註冊,以繼續使用。
unconfirmed: 您必須先完成信箱驗證,以繼續使用。
mailer:
confirmation_instructions:
+ action: 驗證電子郵件地址
+ explanation: 您已經在 %{host} 上以此電子郵件地址建立了一個帳號。您距離啟用它只剩一次點擊之遙了。如果這不是你,請忽略此電子郵件。
+ extra_html: 同時也請看看該實體的規則與我們的服務條款。
subject: 'Mastodon: 信箱驗證'
+ title: 驗證電子郵件地址
+ email_changed:
+ explanation: 您帳號的電子郵件地址被變更為:
+ extra: 如果您並未變更您的電子郵件,那麼很有可能是某人取得了您帳號的存取權限。請立刻變更您的密碼,或是若您的帳號已被鎖定,請聯絡所使用實體的管理員。
+ subject: Mastodon 電子郵件變更
+ title: 新電子郵件地址
password_change:
+ explanation: 您帳號的密碼已變更。
+ extra: 如果您並未變更您的密碼,那麼很有可能是某人取得了您帳號的存取權限。請立刻變更您的密碼,或是若您的帳號已被鎖定,請聯絡所使用實體的管理員。
subject: 'Mastodon: 更改密碼'
+ title: 密碼已變更
+ reconfirmation_instructions:
+ explanation: 確認新的電子郵件地址以變更您的電子郵件。
+ extra: 若此次變更不是由您開啟的,請忽略這個電子郵件。Mastodon 帳號的電子郵件地址在您存取上面的連結前不會變更。
+ subject: Mastodon:%{instance} 的確認電子郵件
+ title: 驗證電子郵件地址
reset_password_instructions:
+ action: 變更密碼
+ explanation: 您為您的帳號請求了一個新密碼。
+ extra: 若您並未請求這個,請忽略此電子郵件。您的密碼在您存取上面的連結並建立一個新的之前不會變更。
subject: 'Mastodon: 重設密碼'
+ title: 重設密碼
unlock_instructions:
subject: 'Mastodon: 帳號解鎖'
omniauth_callbacks:
diff --git a/config/locales/doorkeeper.ar.yml b/config/locales/doorkeeper.ar.yml
index d13c22386..5586b8dc8 100644
--- a/config/locales/doorkeeper.ar.yml
+++ b/config/locales/doorkeeper.ar.yml
@@ -79,12 +79,17 @@ ar:
messages:
access_denied: لقد رفض مالك المَورِدِ أو تصريح السيرفر طلبك.
invalid_client: فشلت المصادقة مع العميل لأنه العميل مجهول أو لغياب المصادقة ضمن العميل أو أنّ أسلوب المصادقة غير مدعومة.
+ invalid_grant: إنّ التصريح المقدَّم غير صالح، سواء انتهت مدة صلاحيته أو تم إلغاؤه أو أنه لا يتطابق مع عنوان إعادة التحويل في طلب التصريح أو أنّ هذا التصريح قد تم تقديمه لعميل آخر.
invalid_redirect_uri: إنّ عنوان إعادة التحويل غير صالح.
+ invalid_request: إنّ هذا الطلب يستلزم مؤشرا أو يحمل قيمة مُعامِل غير مدعومة أو فيه خلل ما.
+ invalid_resource_owner: إنّ المُعرِّفات التي قدّمها صاحب المورِد غير صحيحة أو أنه لا وجود لصاحب المورِد
invalid_scope: المجال المطلوب غير صحيح أو مجهول أو مُعبَّر عنه بشكل خاطئ.
invalid_token:
expired: إنتهت فترة صلاحيته رمز المصادقة
revoked: تم إبطال رمز المصادقة
unknown: رمز المصادقة غير صالح
+ resource_owner_authenticator_not_configured: لقد أخفقت عملية البحث عن صاحب المَورِد لغياب الضبط في Doorkeeper.configure.resource_owner_authenticator.
+ server_error: لقد صادفَ خادوم التصريحات ضروفا غير مواتية، الأمر الذي مَنَعه مِن مواصلة دراسة الطلب.
temporarily_unavailable: تعذر على خادم التفويض معالجة الطلب و ذلك بسبب زيادة مؤقتة في التحميل أو عملية صيانة مبرمجة على الخادم.
unauthorized_client: لا يصرح للعميل بتنفيذ هذا الطلب باستخدام هذه الطريقة.
unsupported_grant_type: هذا النوع من منح التصريح غير معتمد في خادم الترخيص.
diff --git a/config/locales/doorkeeper.fa.yml b/config/locales/doorkeeper.fa.yml
index 6a4be575e..f3db862ca 100644
--- a/config/locales/doorkeeper.fa.yml
+++ b/config/locales/doorkeeper.fa.yml
@@ -3,19 +3,19 @@ fa:
activerecord:
attributes:
doorkeeper/application:
- name: Application name
- redirect_uri: Redirect URI
- scopes: Scopes
- website: Application website
+ name: نام برنامه
+ redirect_uri: نشانی تغییرمسیر
+ scopes: محدوده
+ website: وبگاه برنامه
errors:
models:
doorkeeper/application:
attributes:
redirect_uri:
- fragment_present: cannot contain a fragment.
- invalid_uri: must be a valid URI.
- relative_uri: must be an absolute URI.
- secured_uri: must be an HTTPS/SSL URI.
+ fragment_present: نمیتواند چندتکه باشد.
+ invalid_uri: باید یک نشانی معتبر باشد.
+ relative_uri: باید یک نشانی مطلق باشد.
+ secured_uri: باید یک نشانی HTTPS/SSL باشد.
doorkeeper:
applications:
buttons:
diff --git a/config/locales/doorkeeper.id.yml b/config/locales/doorkeeper.id.yml
index 6db797c87..0a99b86c0 100644
--- a/config/locales/doorkeeper.id.yml
+++ b/config/locales/doorkeeper.id.yml
@@ -35,9 +35,13 @@ id:
redirect_uri: Gunakan satu baris per URI
scopes: Pisahkan scope dengan spasi. Biarkan kosong jika ingin menggunakan scope default.
index:
+ application: Aplikasi
callback_url: URL Callback
+ delete: Hapus
name: Nama
new: Aplikasi baru
+ scopes: Cakupan
+ show: Tampilkan
title: Aplikasi anda
new:
title: Aplikasi Baru
diff --git a/config/locales/doorkeeper.sk.yml b/config/locales/doorkeeper.sk.yml
index b8fd281f7..7a285eb4f 100644
--- a/config/locales/doorkeeper.sk.yml
+++ b/config/locales/doorkeeper.sk.yml
@@ -19,7 +19,7 @@ sk:
doorkeeper:
applications:
buttons:
- authorize: Autorizovať
+ authorize: Overiť
cancel: Zrušiť
destroy: Zničiť
edit: Upraviť
@@ -54,7 +54,7 @@ sk:
title: 'Aplikácia: %{name}'
authorizations:
buttons:
- authorize: Autorizovať
+ authorize: Overiť
deny: Zamietnuť
error:
title: Nastala chyba
diff --git a/config/locales/doorkeeper.zh-TW.yml b/config/locales/doorkeeper.zh-TW.yml
index 01e62df73..2aa271785 100644
--- a/config/locales/doorkeeper.zh-TW.yml
+++ b/config/locales/doorkeeper.zh-TW.yml
@@ -5,12 +5,14 @@ zh-TW:
doorkeeper/application:
name: 名稱
redirect_uri: 重新導向 URI
+ scopes: 範圍
+ website: 應用程式網頁
errors:
models:
doorkeeper/application:
attributes:
redirect_uri:
- fragment_present: URI 不可包含 "#fragment" 部份
+ fragment_present: 不能包含 fragment。
invalid_uri: 必需有正確的 URI.
relative_uri: 必需為絕對 URI.
secured_uri: 必需使用有 HTTPS/SSL 加密的 URI.
@@ -31,11 +33,15 @@ zh-TW:
help:
native_redirect_uri: 使用 %{native_redirect_uri} 作局部測試
redirect_uri: 每行輸入一個 URI
- scopes: 請用半形空格分開權限範圍 (scope)。留空表示使用預設的權限範圍
+ scopes: 請用半形空格分開權限範圍 (scope)。留空表示使用預設的權限範圍。
index:
+ application: 應用程式
callback_url: 回傳網址
+ delete: 刪除
name: 名稱
new: 新增應用程式
+ scopes: 範圍
+ show: 顯示
title: 您的應用程式
new:
title: 新增應用程式
@@ -57,7 +63,7 @@ zh-TW:
prompt: 應用程式 %{client_name} 要求取得您帳號的部份權限
title: 需要授權
show:
- title: Copy this authorization code and paste it to the application.
+ title: 複製此授權碼並貼上到應用程式中。
authorized_applications:
buttons:
revoke: 取消授權
@@ -77,7 +83,7 @@ zh-TW:
invalid_grant: 授權申請不正確、逾期、已被取消、與授權請求內的重新導向 URI 不符、或屬於別的客戶端程式。
invalid_redirect_uri: 不正確的重新導向網址。
invalid_request: 請求缺少必要的參數、包含不支援的參數、或其他輸入錯誤。
- invalid_resource_owner: 資源擁有者的登入資訊錯誤、或無法找到該資源擁有者。
+ invalid_resource_owner: 資源擁有者的登入資訊錯誤、或無法找到該資源擁有者
invalid_scope: 請求的權限範圍不正確、未有定義、或輸入錯誤。
invalid_token:
expired: access token 已過期
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index 8bc2aaa41..84d63d831 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -333,7 +333,7 @@ eo:
subscriptions:
callback_url: Revena URL
confirmed: Konfirmita
- expires_in: Eksvalidiĝas en
+ expires_in: Eksvalidiĝas je
last_delivery: Lasta livero
title: WebSub
topic: Temo
@@ -485,7 +485,7 @@ eo:
max_uses_prompt: Neniu limo
prompt: Krei kaj diskonigi ligilojn al aliaj por doni aliron al ĉi tiu nodo
table:
- expires_at: Eksvalidiĝas
+ expires_at: Eksvalidiĝas je
uses: Uzoj
title: Inviti homojn
landing_strip_html: "%{name} estas uzanto en %{link_to_root_path}. Vi povas sekvi tiun aŭ interagi kun tiu, se vi havas konton ie ajn en la fediverse."
@@ -636,6 +636,15 @@ eo:
two_factor_authentication: Dufaktora aŭtentigo
your_apps: Viaj aplikaĵoj
statuses:
+ attached:
+ description: 'Ligita: %{attached}'
+ image:
+ one: "%{count} bildo"
+ other: "%{count} bildoj"
+ video:
+ one: "%{count} video"
+ other: "%{count} videoj"
+ content_warning: 'Enhava averto: %{warning}'
open_in_web: Malfermi retumile
over_character_limit: limo de %{max} signoj transpasita
pin_errors:
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 1ff309782..090b080e4 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -641,8 +641,8 @@ ja:
one: "%{count} 枚の画像"
other: "%{count} 枚の画像"
video:
- one: "%{count} 枚の動画"
- other: "%{count} 枚の動画"
+ one: "%{count} 本の動画"
+ other: "%{count} 本の動画"
content_warning: '閲覧注意: %{warning}'
open_in_web: Webで開く
over_character_limit: 上限は %{max}文字までです
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 8a11b096a..ba55b3549 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -361,6 +361,7 @@ ko:
your_token: 액세스 토큰
auth:
agreement_html: 이 등록으로 이용규약 과 약관에 동의하는 것으로 간주됩니다.
+ change_password: 패스워드
confirm_email: 확인 메일 승인
delete_account: 계정 삭제
delete_account_html: 계정을 삭제하고 싶은 경우, 여기서 삭제할 수 있습니다. 삭제 전 확인 화면이 표시됩니다.
@@ -373,7 +374,11 @@ ko:
migrate_account_html: 이 계정을 다른 계정으로 리디렉션 하길 원하는 경우 여기에서 설정할 수 있습니다.
or: 또는
or_log_in_with: 다른 방법으로 로그인 하려면
+ providers:
+ cas: CAS
+ saml: SAML
register: 등록하기
+ register_elsewhere: 다른 인스턴스에서 가입
resend_confirmation: 확인 메일을 다시 보내기
reset_password: 비밀번호 재설정
security: 보안
@@ -545,7 +550,9 @@ ko:
trillion: T
unit: ''
pagination:
+ newer: 새로운 툿
next: 다음
+ older: 오래된 툿
prev: 이전
truncate: "…"
preferences:
@@ -629,6 +636,15 @@ ko:
two_factor_authentication: 2단계 인증
your_apps: 애플리케이션
statuses:
+ attached:
+ description: '첨부: %{attached}'
+ image:
+ one: "%{count} 이미지"
+ other: "%{count} 이미지"
+ video:
+ one: "%{count} 영상"
+ other: "%{count} 영상"
+ content_warning: '열람 주의: %{warning}'
open_in_web: Web으로 열기
over_character_limit: 최대 %{max}자까지 입력할 수 있습니다
pin_errors:
diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml
index e49bfd9f9..85eccf091 100644
--- a/config/locales/simple_form.ko.yml
+++ b/config/locales/simple_form.ko.yml
@@ -45,6 +45,7 @@ ko:
setting_default_privacy: 툿 프라이버시
setting_default_sensitive: 미디어를 언제나 민감한 컨텐츠로 설정
setting_delete_modal: 툿 삭제 전 확인 창을 표시
+ setting_display_sensitive_media: 열람주의로 설정 된 이미지도 항상 보여주기
setting_noindex: 검색엔진의 인덱싱을 거절
setting_reduce_motion: 애니메이션 줄이기
setting_system_font_ui: 시스템의 초기 설정 폰트를 사용
@@ -53,6 +54,7 @@ ko:
severity: 심각도
type: 불러오기 종류
username: 유저 이름
+ username_or_email: 유저네임 또는 이메일
interactions:
must_be_follower: 나를 팔로우 하지 않는 사람에게서 온 알림을 차단
must_be_following: 내가 팔로우 하지 않는 사람에게서 온 알림을 차단
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index a0e1a597c..2ee25b372 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -580,7 +580,12 @@ sk:
browser: Prehliadač
browsers:
alipay: Alipay
+ chrome: Google Chrome
+ edge: Microsoft Edge
+ electron: Electron
+ firefox: Mozilla Firefox
generic: Neznámy prehliadač
+ ie: Internet Explorer
current_session: Aktuálna sezóna
description: "%{browser} na %{platform}"
explanation: Tieto sú prehliadače ktoré sú teraz prihlásené na tvoj Mastodon účet.
@@ -607,12 +612,22 @@ sk:
two_factor_authentication: Dvoj-faktorové overenie
your_apps: Tvoje aplikácie
statuses:
+ attached:
+ description: 'Priložené: %{attached}'
+ image:
+ one: "%{count} obrázok"
+ other: "%{count} obrázkov"
+ video:
+ one: "%{count} video"
+ other: "%{count} videí"
+ content_warning: 'Varovanie o obsahu: %{warning}'
open_in_web: Otvor v okne prehliadača
over_character_limit: limit počtu %{max} znakov bol presiahnutý
pin_errors:
limit: Už ste si pripli ten najvyšší možný počet príspevkov
ownership: Nemožno pripnúť príspevok od niekoho iného
private: Neverejné príspevky nemôžu byť pripnuté
+ reblog: Pozdvihnutie sa nedá pripnúť
show_more: Ukáž viac
visibilities:
private: Iba pre sledovateľov
@@ -628,11 +643,20 @@ sk:
sensitive_content: Senzitívny obsah
terms:
title: Podmienky užívania, a pravidlá o súkromí pre %{instance}
+ themes:
+ default: Mastodon
+ time:
+ formats:
+ default: "%b %d, %R, %H:%M"
two_factor_authentication:
+ code_hint: Pre potvrdenie teraz zadaj kód vygenerovaný pomocou tvojej overovacej aplikácie
+ description_html: Ak povolíš dvoj-faktorové overovanie, na prihlásenie potom budeš potrebovať svoj telefón, ktorý vygeneruje prístupové kódy, čo musíš zadať.
+ disable: Zakáž
enable: Povoliť
enabled: Dvoj-faktorové overovanie je povolené
enabled_success: Dvoj-faktorové overovanie bolo úspešne povolené
generate_recovery_codes: Vygeneruj zálohové kódy
+ instructions_html: "Naskenuj tento QR kód do Google Autentikátora, alebo do podobnej TOTP aplikácie pomocou svojho telefónu. Od tejto chvíle bude táto aplikácia pre teba generovať kódy ktoré musíš zadať aby si sa prihlásil/a."
lost_recovery_codes: Zálohové kódy ti umožnia dostať sa k svojmu účtu ak stratíš telefón. Pokiaľ si stratila svoje zálohové kódy, môžeš si ich tu znovu vygenerovať. Tvoje staré zálohové kódy budú zneplatnené.
manual_instructions: 'Pokiaľ nemôžeš oskenovať daný QR kód, a potrebuješ ho zadať ručne, tu je tajomstvo v textovom formáte:'
recovery_codes: Zálohuj kódy pre obnovu
From 4fd71accd419fb79cc75e0ebf30df374d174ebf5 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Mon, 2 Apr 2018 13:44:19 +0200
Subject: [PATCH 030/442] Fix issues with sending direct messages from user
profile (#6999)
* Clear compose textarea when starting a new direct message
Previous behaviour resulted in potentially misdirected direct messages.
* Hide search when starting to compose a direct message
---
app/javascript/mastodon/reducers/compose.js | 2 +-
app/javascript/mastodon/reducers/search.js | 7 ++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index a48c46941..1f4177585 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -265,7 +265,7 @@ export default function compose(state = initialState, action) {
.set('idempotencyKey', uuid());
case COMPOSE_DIRECT:
return state
- .update('text', text => `${text}@${action.account.get('acct')} `)
+ .update('text', text => `@${action.account.get('acct')} `)
.set('privacy', 'direct')
.set('focusDate', new Date())
.set('idempotencyKey', uuid());
diff --git a/app/javascript/mastodon/reducers/search.js b/app/javascript/mastodon/reducers/search.js
index 08d90e4e8..56fd7226b 100644
--- a/app/javascript/mastodon/reducers/search.js
+++ b/app/javascript/mastodon/reducers/search.js
@@ -4,7 +4,11 @@ import {
SEARCH_FETCH_SUCCESS,
SEARCH_SHOW,
} from '../actions/search';
-import { COMPOSE_MENTION, COMPOSE_REPLY } from '../actions/compose';
+import {
+ COMPOSE_MENTION,
+ COMPOSE_REPLY,
+ COMPOSE_DIRECT,
+} from '../actions/compose';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
const initialState = ImmutableMap({
@@ -29,6 +33,7 @@ export default function search(state = initialState, action) {
return state.set('hidden', false);
case COMPOSE_REPLY:
case COMPOSE_MENTION:
+ case COMPOSE_DIRECT:
return state.set('hidden', true);
case SEARCH_FETCH_SUCCESS:
return state.set('results', ImmutableMap({
From e7a17167015dca6864f31152c47334c3b3a857a2 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Mon, 2 Apr 2018 13:45:07 +0200
Subject: [PATCH 031/442] Implement the ability for an Administrator or
Moderator to remove an account avatar (#6998)
---
app/controllers/admin/accounts_controller.rb | 13 ++++++++++++-
app/helpers/admin/action_logs_helper.rb | 2 +-
app/policies/account_policy.rb | 4 ++++
app/views/admin/accounts/show.html.haml | 8 ++++++++
config/locales/en.yml | 3 +++
config/routes.rb | 1 +
6 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/app/controllers/admin/accounts_controller.rb b/app/controllers/admin/accounts_controller.rb
index 7428c3f22..e7ca6b907 100644
--- a/app/controllers/admin/accounts_controller.rb
+++ b/app/controllers/admin/accounts_controller.rb
@@ -2,7 +2,7 @@
module Admin
class AccountsController < BaseController
- before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :enable, :disable, :memorialize]
+ before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload, :remove_avatar, :enable, :disable, :memorialize]
before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
before_action :require_local_account!, only: [:enable, :disable, :memorialize]
@@ -60,6 +60,17 @@ module Admin
redirect_to admin_account_path(@account.id)
end
+ def remove_avatar
+ authorize @account, :remove_avatar?
+
+ @account.avatar = nil
+ @account.save!
+
+ log_action :remove_avatar, @account.user
+
+ redirect_to admin_account_path(@account.id)
+ end
+
private
def set_account
diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb
index 4475034a5..78278c700 100644
--- a/app/helpers/admin/action_logs_helper.rb
+++ b/app/helpers/admin/action_logs_helper.rb
@@ -86,7 +86,7 @@ module Admin::ActionLogsHelper
opposite_verbs?(log) ? 'negative' : 'positive'
when :update, :reset_password, :disable_2fa, :memorialize
'neutral'
- when :demote, :silence, :disable, :suspend
+ when :demote, :silence, :disable, :suspend, :remove_avatar
'negative'
when :destroy
opposite_verbs?(log) ? 'positive' : 'negative'
diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb
index 85e2c8419..efabe80d0 100644
--- a/app/policies/account_policy.rb
+++ b/app/policies/account_policy.rb
@@ -29,6 +29,10 @@ class AccountPolicy < ApplicationPolicy
admin?
end
+ def remove_avatar?
+ staff?
+ end
+
def subscribe?
admin?
end
diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml
index dbbf5fc09..fecfd6cc8 100644
--- a/app/views/admin/accounts/show.html.haml
+++ b/app/views/admin/accounts/show.html.haml
@@ -14,6 +14,14 @@
%th= t('admin.accounts.display_name')
%td= @account.display_name
+ %tr
+ %th= t('admin.accounts.avatar')
+ %th
+ = link_to @account.avatar.url(:original) do
+ = image_tag @account.avatar.url(:original), alt: '', width: 40, height: 40, class: 'avatar'
+ - if @account.local? && @account.avatar?
+ = table_link_to 'trash', t('admin.accounts.remove_avatar'), remove_avatar_admin_account_path(@account.id), method: :post, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:remove_avatar, @account)
+
- if @account.local?
%tr
%th= t('admin.accounts.role')
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e3d76971b..fb2bbf4fe 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -60,6 +60,7 @@ en:
destroyed_msg: Moderation note successfully destroyed!
accounts:
are_you_sure: Are you sure?
+ avatar: Avatar
by_domain: Domain
confirm: Confirm
confirmed: Confirmed
@@ -108,6 +109,7 @@ en:
public: Public
push_subscription_expires: PuSH subscription expires
redownload: Refresh avatar
+ remove_avatar: Remove avatar
reset: Reset
reset_password: Reset password
resubscribe: Resubscribe
@@ -150,6 +152,7 @@ en:
enable_user: "%{name} enabled login for user %{target}"
memorialize_account: "%{name} turned %{target}'s account into a memoriam page"
promote_user: "%{name} promoted user %{target}"
+ remove_avatar_user: "%{name} removed %{target}'s avatar"
reset_password_user: "%{name} reset password of user %{target}"
resolve_report: "%{name} dismissed report %{target}"
silence_account: "%{name} silenced %{target}'s account"
diff --git a/config/routes.rb b/config/routes.rb
index 0542cb680..9a4460562 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -144,6 +144,7 @@ Rails.application.routes.draw do
post :enable
post :disable
post :redownload
+ post :remove_avatar
post :memorialize
end
From 2c51bc0ca5a4c3a4bb140b4b40dabdda859ebb94 Mon Sep 17 00:00:00 2001
From: unarist
Date: Mon, 2 Apr 2018 21:51:02 +0900
Subject: [PATCH 032/442] Add missing rejection handling for Promises (#7008)
* Add eslint-plugin-promise to detect uncaught rejections
* Move alert generation for errors to actions/alert
* Add missing rejection handling for Promises
* Use catch() instead of onReject on then()
Then it will catches rejection from onFulfilled. This detection can be
disabled by `allowThen` option, though.
---
.eslintrc.yml | 3 ++
app/javascript/mastodon/actions/accounts.js | 2 +-
app/javascript/mastodon/actions/alerts.js | 25 ++++++++++++++++
app/javascript/mastodon/actions/compose.js | 7 ++++-
app/javascript/mastodon/actions/lists.js | 3 +-
.../actions/push_notifications/registerer.js | 15 ++++------
app/javascript/mastodon/actions/settings.js | 5 +++-
.../mastodon/containers/status_container.js | 6 +++-
.../features/ui/components/embed_modal.js | 3 ++
app/javascript/mastodon/middleware/errors.js | 24 ++-------------
app/javascript/mastodon/storage/modifier.js | 30 ++++++++++++++-----
package.json | 1 +
yarn.lock | 4 +++
13 files changed, 84 insertions(+), 44 deletions(-)
diff --git a/.eslintrc.yml b/.eslintrc.yml
index cf276a16f..576e5b70a 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -13,6 +13,7 @@ plugins:
- react
- jsx-a11y
- import
+- promise
parserOptions:
sourceType: module
@@ -152,3 +153,5 @@ rules:
- "app/javascript/**/__tests__/**"
import/no-unresolved: error
import/no-webpack-loader-syntax: error
+
+ promise/catch-or-return: error
diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js
index 7cacff909..28ae56763 100644
--- a/app/javascript/mastodon/actions/accounts.js
+++ b/app/javascript/mastodon/actions/accounts.js
@@ -103,7 +103,7 @@ export function fetchAccount(id) {
dispatch(importFetchedAccount(response.data));
})).then(() => {
dispatch(fetchAccountSuccess());
- }, error => {
+ }).catch(error => {
dispatch(fetchAccountFail(id, error));
});
};
diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js
index f37fdeeb6..3f5d7ef46 100644
--- a/app/javascript/mastodon/actions/alerts.js
+++ b/app/javascript/mastodon/actions/alerts.js
@@ -1,3 +1,10 @@
+import { defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' },
+ unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' },
+});
+
export const ALERT_SHOW = 'ALERT_SHOW';
export const ALERT_DISMISS = 'ALERT_DISMISS';
export const ALERT_CLEAR = 'ALERT_CLEAR';
@@ -22,3 +29,21 @@ export function showAlert(title, message) {
message,
};
};
+
+export function showAlertForError(error) {
+ if (error.response) {
+ const { data, status, statusText } = error.response;
+
+ let message = statusText;
+ let title = `${status}`;
+
+ if (data.error) {
+ message = data.error;
+ }
+
+ return showAlert(title, message);
+ } else {
+ console.error(error);
+ return showAlert(messages.unexpectedTitle, messages.unexpectedMessage);
+ }
+}
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index 2138f9426..59aa6f98d 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -1,11 +1,12 @@
import api from '../api';
-import { CancelToken } from 'axios';
+import { CancelToken, isCancel } from 'axios';
import { throttle } from 'lodash';
import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
import { tagHistory } from '../settings';
import { useEmoji } from './emojis';
import { importFetchedAccounts } from './importer';
import { updateTimeline } from './timelines';
+import { showAlertForError } from './alerts';
let cancelFetchComposeSuggestionsAccounts;
@@ -291,6 +292,10 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
}).then(response => {
dispatch(importFetchedAccounts(response.data));
dispatch(readyComposeSuggestionsAccounts(token, response.data));
+ }).catch(error => {
+ if (!isCancel(error)) {
+ dispatch(showAlertForError(error));
+ }
});
}, 200, { leading: true, trailing: true });
diff --git a/app/javascript/mastodon/actions/lists.js b/app/javascript/mastodon/actions/lists.js
index 12d60e3a3..12cb17159 100644
--- a/app/javascript/mastodon/actions/lists.js
+++ b/app/javascript/mastodon/actions/lists.js
@@ -1,5 +1,6 @@
import api from '../api';
import { importFetchedAccounts } from './importer';
+import { showAlertForError } from './alerts';
export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST';
export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS';
@@ -236,7 +237,7 @@ export const fetchListSuggestions = q => (dispatch, getState) => {
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
dispatch(importFetchedAccounts(data));
dispatch(fetchListSuggestionsReady(q, data));
- });
+ }).catch(error => dispatch(showAlertForError(error)));
};
export const fetchListSuggestionsReady = (query, accounts) => ({
diff --git a/app/javascript/mastodon/actions/push_notifications/registerer.js b/app/javascript/mastodon/actions/push_notifications/registerer.js
index 51e68cad1..f17d929a6 100644
--- a/app/javascript/mastodon/actions/push_notifications/registerer.js
+++ b/app/javascript/mastodon/actions/push_notifications/registerer.js
@@ -116,14 +116,11 @@ export function register () {
pushNotificationsSetting.remove(me);
}
- try {
- getRegistration()
- .then(getPushSubscription)
- .then(unsubscribe);
- } catch (e) {
-
- }
- });
+ return getRegistration()
+ .then(getPushSubscription)
+ .then(unsubscribe);
+ })
+ .catch(console.warn);
} else {
console.warn('Your browser does not support Web Push Notifications.');
}
@@ -143,6 +140,6 @@ export function saveSettings() {
if (me) {
pushNotificationsSetting.set(me, data);
}
- });
+ }).catch(console.warn);
};
}
diff --git a/app/javascript/mastodon/actions/settings.js b/app/javascript/mastodon/actions/settings.js
index b96383daa..5634a11ef 100644
--- a/app/javascript/mastodon/actions/settings.js
+++ b/app/javascript/mastodon/actions/settings.js
@@ -1,5 +1,6 @@
import api from '../api';
import { debounce } from 'lodash';
+import { showAlertForError } from './alerts';
export const SETTING_CHANGE = 'SETTING_CHANGE';
export const SETTING_SAVE = 'SETTING_SAVE';
@@ -23,7 +24,9 @@ const debouncedSave = debounce((dispatch, getState) => {
const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS();
- api(getState).put('/api/web/settings', { data }).then(() => dispatch({ type: SETTING_SAVE }));
+ api(getState).put('/api/web/settings', { data })
+ .then(() => dispatch({ type: SETTING_SAVE }))
+ .catch(error => dispatch(showAlertForError(error)));
}, 5000, { trailing: true });
export function saveSettings() {
diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js
index 8ba1015b5..4579bd132 100644
--- a/app/javascript/mastodon/containers/status_container.js
+++ b/app/javascript/mastodon/containers/status_container.js
@@ -27,6 +27,7 @@ import { initReport } from '../actions/reports';
import { openModal } from '../actions/modal';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { boostModal, deleteModal } from '../initial_state';
+import { showAlertForError } from '../actions/alerts';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
@@ -83,7 +84,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
},
onEmbed (status) {
- dispatch(openModal('EMBED', { url: status.get('url') }));
+ dispatch(openModal('EMBED', {
+ url: status.get('url'),
+ onError: error => dispatch(showAlertForError(error)),
+ }));
},
onDelete (status) {
diff --git a/app/javascript/mastodon/features/ui/components/embed_modal.js b/app/javascript/mastodon/features/ui/components/embed_modal.js
index d440a8826..52aab00d0 100644
--- a/app/javascript/mastodon/features/ui/components/embed_modal.js
+++ b/app/javascript/mastodon/features/ui/components/embed_modal.js
@@ -10,6 +10,7 @@ export default class EmbedModal extends ImmutablePureComponent {
static propTypes = {
url: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
+ onError: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
@@ -35,6 +36,8 @@ export default class EmbedModal extends ImmutablePureComponent {
iframeDocument.body.style.margin = 0;
this.iframe.width = iframeDocument.body.scrollWidth;
this.iframe.height = iframeDocument.body.scrollHeight;
+ }).catch(error => {
+ this.props.onError(error);
});
}
diff --git a/app/javascript/mastodon/middleware/errors.js b/app/javascript/mastodon/middleware/errors.js
index 72e5631e6..3cebb42e0 100644
--- a/app/javascript/mastodon/middleware/errors.js
+++ b/app/javascript/mastodon/middleware/errors.js
@@ -1,34 +1,14 @@
-import { defineMessages } from 'react-intl';
-import { showAlert } from '../actions/alerts';
+import { showAlertForError } from '../actions/alerts';
const defaultFailSuffix = 'FAIL';
-const messages = defineMessages({
- unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' },
- unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' },
-});
-
export default function errorsMiddleware() {
return ({ dispatch }) => next => action => {
if (action.type && !action.skipAlert) {
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
if (action.type.match(isFail)) {
- if (action.error.response) {
- const { data, status, statusText } = action.error.response;
-
- let message = statusText;
- let title = `${status}`;
-
- if (data.error) {
- message = data.error;
- }
-
- dispatch(showAlert(title, message));
- } else {
- console.error(action.error);
- dispatch(showAlert(messages.unexpectedTitle, messages.unexpectedMessage));
- }
+ dispatch(showAlertForError(action.error));
}
}
diff --git a/app/javascript/mastodon/storage/modifier.js b/app/javascript/mastodon/storage/modifier.js
index 1bec04d0f..4773d07a9 100644
--- a/app/javascript/mastodon/storage/modifier.js
+++ b/app/javascript/mastodon/storage/modifier.js
@@ -9,6 +9,12 @@ const limit = 1024;
// https://webkit.org/status/#specification-service-workers
const asyncCache = window.caches ? caches.open('mastodon-system') : Promise.reject();
+function printErrorIfAvailable(error) {
+ if (error) {
+ console.warn(error);
+ }
+}
+
function put(name, objects, onupdate, oncreate) {
return asyncDB.then(db => new Promise((resolve, reject) => {
const putTransaction = db.transaction(name, 'readwrite');
@@ -77,7 +83,9 @@ function evictAccountsByRecords(records) {
function evict(toEvict) {
toEvict.forEach(record => {
- asyncCache.then(cache => accountAssetKeys.forEach(key => cache.delete(records[key])));
+ asyncCache
+ .then(cache => accountAssetKeys.forEach(key => cache.delete(records[key])))
+ .catch(printErrorIfAvailable);
accountsMovedIndex.getAll(record.id).onsuccess = ({ target }) => evict(target.result);
@@ -90,11 +98,11 @@ function evictAccountsByRecords(records) {
}
evict(records);
- });
+ }).catch(printErrorIfAvailable);
}
export function evictStatus(id) {
- return evictStatuses([id]);
+ evictStatuses([id]);
}
export function evictStatuses(ids) {
@@ -110,7 +118,7 @@ export function evictStatuses(ids) {
idIndex.getKey(id).onsuccess =
({ target }) => target.result && store.delete(target.result);
});
- });
+ }).catch(printErrorIfAvailable);
}
function evictStatusesByRecords(records) {
@@ -127,7 +135,9 @@ export function putAccounts(records) {
const oldURL = target.result[key];
if (newURL !== oldURL) {
- asyncCache.then(cache => cache.delete(oldURL));
+ asyncCache
+ .then(cache => cache.delete(oldURL))
+ .catch(printErrorIfAvailable);
}
});
@@ -145,10 +155,14 @@ export function putAccounts(records) {
oncomplete();
}).then(records => {
evictAccountsByRecords(records);
- asyncCache.then(cache => cache.addAll(newURLs));
- });
+ asyncCache
+ .then(cache => cache.addAll(newURLs))
+ .catch(printErrorIfAvailable);
+ }).catch(printErrorIfAvailable);
}
export function putStatuses(records) {
- put('statuses', records).then(evictStatusesByRecords);
+ put('statuses', records)
+ .then(evictStatusesByRecords)
+ .catch(printErrorIfAvailable);
}
diff --git a/package.json b/package.json
index dfba49afc..d4de3a157 100644
--- a/package.json
+++ b/package.json
@@ -129,6 +129,7 @@
"eslint": "^4.15.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsx-a11y": "^5.1.1",
+ "eslint-plugin-promise": "^3.7.0",
"eslint-plugin-react": "^7.5.1",
"jest": "^21.2.1",
"raf": "^3.4.0",
diff --git a/yarn.lock b/yarn.lock
index a306ebf55..866b24c7a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2433,6 +2433,10 @@ eslint-plugin-jsx-a11y@^5.1.1:
emoji-regex "^6.1.0"
jsx-ast-utils "^1.4.0"
+eslint-plugin-promise@^3.7.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz#f4bde5c2c77cdd69557a8f69a24d1ad3cfc9e67e"
+
eslint-plugin-react@^7.5.1:
version "7.5.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.5.1.tgz#52e56e8d80c810de158859ef07b880d2f56ee30b"
From 36eac8ba9011f225f7f949bbf1ca173832561f10 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Mon, 2 Apr 2018 19:19:51 +0200
Subject: [PATCH 033/442] Do not default SMTP verify mode to "peer", default to
"none" (#6996)
---
lib/tasks/mastodon.rake | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index cfd6a1d25..505c7e0fa 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -256,11 +256,7 @@ namespace :mastodon do
q.modify :strip
end
- env['SMTP_OPENSSL_VERIFY_MODE'] = prompt.ask('SMTP OpenSSL verify mode:') do |q|
- q.required
- q.default 'peer'
- q.modify :strip
- end
+ env['SMTP_OPENSSL_VERIFY_MODE'] = prompt.select('SMTP OpenSSL verify mode:', %w(none peer client_once fail_if_no_peer_cert))
end
env['SMTP_FROM_ADDRESS'] = prompt.ask('E-mail address to send e-mails "from":') do |q|
From e85cffb2362f914c0f2f7ced4112430b30bc7997 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Mon, 2 Apr 2018 22:04:14 +0200
Subject: [PATCH 034/442] Feature: Report improvements (#6967) (#7000)
* Implement Assignment of Reports (#6967)
* Change translation of admin.report.comment.label to "Report Comment" for clarity
As we'll soon add the ability for reports to have comments on them, this clarification makes sense.
* Implement notes for Reports
This enables moderators to leave comments about a report whilst they work on it
* Fix display of report moderation notes
* Allow reports to be reopened / marked as unresolved
* Redirect to reports listing upon resolution of report
* Implement "resolve with note" functionality
* Add inverse relationship for report notes
* Remove additional database querying when loading report notes
* Fix tests for reports
* Fix localisations for report notes / reports
---
.../admin/report_notes_controller.rb | 49 +++++++++++
app/controllers/admin/reports_controller.rb | 20 ++++-
app/helpers/admin/action_logs_helper.rb | 2 +-
app/models/account.rb | 2 +
app/models/report.rb | 4 +
app/models/report_note.rb | 21 +++++
app/policies/report_note_policy.rb | 17 ++++
.../admin/report_notes/_report_note.html.haml | 11 +++
app/views/admin/reports/_report.html.haml | 5 ++
app/views/admin/reports/index.html.haml | 1 +
app/views/admin/reports/show.html.haml | 84 +++++++++++++++----
config/locales/en.yml | 22 ++++-
config/routes.rb | 2 +
...1200_add_assigned_account_id_to_reports.rb | 5 ++
.../20180402040909_create_report_notes.rb | 14 ++++
db/schema.rb | 16 +++-
.../admin/reports_controller_spec.rb | 40 ++++++++-
17 files changed, 290 insertions(+), 25 deletions(-)
create mode 100644 app/controllers/admin/report_notes_controller.rb
create mode 100644 app/models/report_note.rb
create mode 100644 app/policies/report_note_policy.rb
create mode 100644 app/views/admin/report_notes/_report_note.html.haml
create mode 100644 db/migrate/20180402031200_add_assigned_account_id_to_reports.rb
create mode 100644 db/migrate/20180402040909_create_report_notes.rb
diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb
new file mode 100644
index 000000000..ef8c0f469
--- /dev/null
+++ b/app/controllers/admin/report_notes_controller.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Admin
+ class ReportNotesController < BaseController
+ before_action :set_report_note, only: [:destroy]
+
+ def create
+ authorize ReportNote, :create?
+
+ @report_note = current_account.report_notes.new(resource_params)
+
+ if @report_note.save
+ if params[:create_and_resolve]
+ @report_note.report.update!(action_taken: true, action_taken_by_account_id: current_account.id)
+ log_action :resolve, @report_note.report
+
+ redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
+ else
+ redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.created_msg')
+ end
+ else
+ @report = @report_note.report
+ @report_notes = @report.notes.latest
+ @form = Form::StatusBatch.new
+
+ render template: 'admin/reports/show'
+ end
+ end
+
+ def destroy
+ authorize @report_note, :destroy?
+ @report_note.destroy!
+ redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.destroyed_msg')
+ end
+
+ private
+
+ def resource_params
+ params.require(:report_note).permit(
+ :content,
+ :report_id
+ )
+ end
+
+ def set_report_note
+ @report_note = ReportNote.find(params[:id])
+ end
+ end
+end
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index 75db6b78a..fc3785e3b 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -11,19 +11,35 @@ module Admin
def show
authorize @report, :show?
+ @report_note = @report.notes.new
+ @report_notes = @report.notes.latest
@form = Form::StatusBatch.new
end
def update
authorize @report, :update?
process_report
- redirect_to admin_report_path(@report)
+
+ if @report.action_taken?
+ redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
+ else
+ redirect_to admin_report_path(@report)
+ end
end
private
def process_report
case params[:outcome].to_s
+ when 'assign_to_self'
+ @report.update!(assigned_account_id: current_account.id)
+ log_action :assigned_to_self, @report
+ when 'unassign'
+ @report.update!(assigned_account_id: nil)
+ log_action :unassigned, @report
+ when 'reopen'
+ @report.update!(action_taken: false, action_taken_by_account_id: nil)
+ log_action :reopen, @report
when 'resolve'
@report.update!(action_taken_by_current_attributes)
log_action :resolve, @report
@@ -32,11 +48,13 @@ module Admin
log_action :resolve, @report
log_action :suspend, @report.target_account
resolve_all_target_account_reports
+ @report.reload
when 'silence'
@report.target_account.update!(silenced: true)
log_action :resolve, @report
log_action :silence, @report.target_account
resolve_all_target_account_reports
+ @report.reload
else
raise ActiveRecord::RecordNotFound
end
diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb
index 78278c700..7c26c0b05 100644
--- a/app/helpers/admin/action_logs_helper.rb
+++ b/app/helpers/admin/action_logs_helper.rb
@@ -86,7 +86,7 @@ module Admin::ActionLogsHelper
opposite_verbs?(log) ? 'negative' : 'positive'
when :update, :reset_password, :disable_2fa, :memorialize
'neutral'
- when :demote, :silence, :disable, :suspend, :remove_avatar
+ when :demote, :silence, :disable, :suspend, :remove_avatar, :reopen
'negative'
when :destroy
opposite_verbs?(log) ? 'positive' : 'negative'
diff --git a/app/models/account.rb b/app/models/account.rb
index a34b6a2d3..446144a3e 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -95,6 +95,8 @@ class Account < ApplicationRecord
has_many :reports
has_many :targeted_reports, class_name: 'Report', foreign_key: :target_account_id
+ has_many :report_notes, dependent: :destroy
+
# Moderation notes
has_many :account_moderation_notes, dependent: :destroy
has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy
diff --git a/app/models/report.rb b/app/models/report.rb
index dd123fc15..f5b37cb6d 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -12,12 +12,16 @@
# account_id :integer not null
# action_taken_by_account_id :integer
# target_account_id :integer not null
+# assigned_account_id :integer
#
class Report < ApplicationRecord
belongs_to :account
belongs_to :target_account, class_name: 'Account'
belongs_to :action_taken_by_account, class_name: 'Account', optional: true
+ belongs_to :assigned_account, class_name: 'Account', optional: true
+
+ has_many :notes, class_name: 'ReportNote', foreign_key: :report_id, inverse_of: :report, dependent: :destroy
scope :unresolved, -> { where(action_taken: false) }
scope :resolved, -> { where(action_taken: true) }
diff --git a/app/models/report_note.rb b/app/models/report_note.rb
new file mode 100644
index 000000000..3d12cf7b6
--- /dev/null
+++ b/app/models/report_note.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+# == Schema Information
+#
+# Table name: report_notes
+#
+# id :integer not null, primary key
+# content :text not null
+# report_id :integer not null
+# account_id :integer not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class ReportNote < ApplicationRecord
+ belongs_to :account
+ belongs_to :report, inverse_of: :notes
+
+ scope :latest, -> { reorder('created_at ASC') }
+
+ validates :content, presence: true, length: { maximum: 500 }
+end
diff --git a/app/policies/report_note_policy.rb b/app/policies/report_note_policy.rb
new file mode 100644
index 000000000..694bc096b
--- /dev/null
+++ b/app/policies/report_note_policy.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ReportNotePolicy < ApplicationPolicy
+ def create?
+ staff?
+ end
+
+ def destroy?
+ admin? || owner?
+ end
+
+ private
+
+ def owner?
+ record.account_id == current_account&.id
+ end
+end
diff --git a/app/views/admin/report_notes/_report_note.html.haml b/app/views/admin/report_notes/_report_note.html.haml
new file mode 100644
index 000000000..60ac5d0d5
--- /dev/null
+++ b/app/views/admin/report_notes/_report_note.html.haml
@@ -0,0 +1,11 @@
+%tr
+ %td
+ %p
+ %strong= report_note.account.acct
+ on
+ %time.formatted{ datetime: report_note.created_at.iso8601, title: l(report_note.created_at) }
+ = l report_note.created_at
+ = table_link_to 'trash', t('admin.reports.notes.delete'), admin_report_note_path(report_note), method: :delete if can?(:destroy, report_note)
+ %br/
+ %br/
+ = simple_format(h(report_note.content))
diff --git a/app/views/admin/reports/_report.html.haml b/app/views/admin/reports/_report.html.haml
index d5eb161b9..d266f4840 100644
--- a/app/views/admin/reports/_report.html.haml
+++ b/app/views/admin/reports/_report.html.haml
@@ -17,5 +17,10 @@
%span{ title: t('admin.accounts.media_attachments') }
= fa_icon('camera')
= report.media_attachments.count
+ %td
+ - if report.assigned_account.nil?
+ \-
+ - else
+ = link_to report.assigned_account.acct, admin_account_path(report.assigned_account.id)
%td
= table_link_to 'circle', t('admin.reports.view'), admin_report_path(report)
diff --git a/app/views/admin/reports/index.html.haml b/app/views/admin/reports/index.html.haml
index 577c68a86..3b127c4fc 100644
--- a/app/views/admin/reports/index.html.haml
+++ b/app/views/admin/reports/index.html.haml
@@ -20,6 +20,7 @@
%th= t('admin.reports.reported_by')
%th= t('admin.reports.comment.label')
%th= t('admin.reports.report_contents')
+ %th= t('admin.reports.assigned')
%th
%tbody
= render @reports
diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml
index 5747cc274..e7634a034 100644
--- a/app/views/admin/reports/show.html.haml
+++ b/app/views/admin/reports/show.html.haml
@@ -4,24 +4,68 @@
- content_for :page_title do
= t('admin.reports.report', id: @report.id)
+%div{ style: 'overflow: hidden; margin-bottom: 20px' }
+ - if !@report.action_taken?
+ %div{ style: 'float: right' }
+ = link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
+ = link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
+ %div{ style: 'float: left' }
+ = link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button'
+ - else
+ = link_to t('admin.reports.mark_as_unresolved'), admin_report_path(@report, outcome: 'reopen'), method: :put, class: 'button'
+
+.table-wrapper
+ %table.table.inline-table
+ %tbody
+ %tr
+ %th= t('admin.reports.updated_at')
+ %td{colspan: 2}
+ %time.formatted{ datetime: @report.updated_at.iso8601 }
+ %tr
+ %th= t('admin.reports.status')
+ %td{colspan: 2}
+ - if @report.action_taken?
+ = t('admin.reports.resolved')
+ = table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
+ - else
+ = t('admin.reports.unresolved')
+ - if !@report.action_taken_by_account.nil?
+ %tr
+ %th= t('admin.reports.action_taken_by')
+ %td= @report.action_taken_by_account.acct
+ - else
+ %tr
+ %th= t('admin.reports.assigned')
+ %td
+ - if @report.assigned_account.nil?
+ \-
+ - else
+ = link_to @report.assigned_account.acct, admin_account_path(@report.assigned_account.id)
+ %td{style: "text-align: right"}
+ - if @report.assigned_account != current_user.account
+ = table_link_to 'user', t('admin.reports.assign_to_self'), admin_report_path(@report, outcome: 'assign_to_self'), method: :put
+ - if !@report.assigned_account.nil?
+ = table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put
+
.report-accounts
.report-accounts__item
- %strong= t('admin.reports.reported_account')
+ %h3= t('admin.reports.reported_account')
= render 'authorize_follows/card', account: @report.target_account, admin: true
= render 'admin/accounts/card', account: @report.target_account
.report-accounts__item
- %strong= t('admin.reports.reported_by')
+ %h3= t('admin.reports.reported_by')
= render 'authorize_follows/card', account: @report.account, admin: true
= render 'admin/accounts/card', account: @report.account
-%p
- %strong= t('admin.reports.comment.label')
- \:
- = simple_format(@report.comment.presence || t('admin.reports.comment.none'))
+%h3= t('admin.reports.comment.label')
+
+= simple_format(@report.comment.presence || t('admin.reports.comment.none'))
- unless @report.statuses.empty?
%hr/
+ %h3= t('admin.reports.statuses')
+
= form_for(@form, url: admin_report_reported_statuses_path(@report.id)) do |f|
.batch-form-box
.batch-checkbox-all
@@ -46,14 +90,20 @@
%hr/
-- if !@report.action_taken?
- %div{ style: 'overflow: hidden' }
- %div{ style: 'float: right' }
- = link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
- = link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
- %div{ style: 'float: left' }
- = link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button'
-- elsif !@report.action_taken_by_account.nil?
- %p
- %strong #{t('admin.reports.action_taken_by')}:
- = @report.action_taken_by_account.acct
+%h3= t('admin.reports.notes.label')
+
+- if @report_notes.length > 0
+ .table-wrapper
+ %table.table
+ %thead
+ %tr
+ %th
+ %tbody
+ = render @report_notes
+
+= simple_form_for @report_note, url: admin_report_notes_path do |f|
+ = render 'shared/error_messages', object: @report_note
+ = f.input :content
+ = f.hidden_field :report_id
+ = f.button :button, t('admin.reports.notes.create'), type: :submit
+ = f.button :button, t('admin.reports.notes.create_and_resolve'), type: :submit, name: :create_and_resolve
diff --git a/config/locales/en.yml b/config/locales/en.yml
index fb2bbf4fe..51d9c906d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -137,6 +137,7 @@ en:
web: Web
action_logs:
actions:
+ assigned_to_self_report: "%{name} assigned report %{target} to themselves"
confirm_user: "%{name} confirmed e-mail address of user %{target}"
create_custom_emoji: "%{name} uploaded new emoji %{target}"
create_domain_block: "%{name} blocked domain %{target}"
@@ -153,10 +154,12 @@ en:
memorialize_account: "%{name} turned %{target}'s account into a memoriam page"
promote_user: "%{name} promoted user %{target}"
remove_avatar_user: "%{name} removed %{target}'s avatar"
+ reopen_report: "%{name} reopened report %{target}"
reset_password_user: "%{name} reset password of user %{target}"
- resolve_report: "%{name} dismissed report %{target}"
+ resolve_report: "%{name} resolved report %{target}"
silence_account: "%{name} silenced %{target}'s account"
suspend_account: "%{name} suspended %{target}'s account"
+ unassigned_report: "%{name} unassigned report %{target}"
unsilence_account: "%{name} unsilenced %{target}'s account"
unsuspend_account: "%{name} unsuspended %{target}'s account"
update_custom_emoji: "%{name} updated emoji %{target}"
@@ -242,15 +245,26 @@ en:
expired: Expired
title: Filter
title: Invites
+ report_notes:
+ created_msg: Moderation note successfully created!
+ destroyed_msg: Moderation note successfully destroyed!
reports:
action_taken_by: Action taken by
are_you_sure: Are you sure?
+ assign_to_self: Assign to me
+ assigned: Assigned Moderator
comment:
- label: Comment
+ label: Report Comment
none: None
delete: Delete
id: ID
mark_as_resolved: Mark as resolved
+ mark_as_unresolved: Mark as unresolved
+ notes:
+ create: Add Note
+ create_and_resolve: Resolve with Note
+ delete: Delete
+ label: Notes
nsfw:
'false': Unhide media attachments
'true': Hide media attachments
@@ -259,12 +273,16 @@ en:
reported_account: Reported account
reported_by: Reported by
resolved: Resolved
+ resolved_msg: Report successfully resolved!
silence_account: Silence account
status: Status
+ statuses: Reported Toots
suspend_account: Suspend account
target: Target
title: Reports
+ unassign: Unassign
unresolved: Unresolved
+ updated_at: Updated
view: View
settings:
activity_api_enabled:
diff --git a/config/routes.rb b/config/routes.rb
index 9a4460562..4b5ba5c96 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -137,6 +137,8 @@ Rails.application.routes.draw do
resources :reported_statuses, only: [:create, :update, :destroy]
end
+ resources :report_notes, only: [:create, :destroy]
+
resources :accounts, only: [:index, :show] do
member do
post :subscribe
diff --git a/db/migrate/20180402031200_add_assigned_account_id_to_reports.rb b/db/migrate/20180402031200_add_assigned_account_id_to_reports.rb
new file mode 100644
index 000000000..0456839c4
--- /dev/null
+++ b/db/migrate/20180402031200_add_assigned_account_id_to_reports.rb
@@ -0,0 +1,5 @@
+class AddAssignedAccountIdToReports < ActiveRecord::Migration[5.1]
+ def change
+ add_reference :reports, :assigned_account, null: true, default: nil, foreign_key: { on_delete: :nullify, to_table: :accounts }, index: false
+ end
+end
diff --git a/db/migrate/20180402040909_create_report_notes.rb b/db/migrate/20180402040909_create_report_notes.rb
new file mode 100644
index 000000000..732ddf825
--- /dev/null
+++ b/db/migrate/20180402040909_create_report_notes.rb
@@ -0,0 +1,14 @@
+class CreateReportNotes < ActiveRecord::Migration[5.1]
+ def change
+ create_table :report_notes do |t|
+ t.text :content, null: false
+ t.references :report, null: false
+ t.references :account, null: false
+
+ t.timestamps
+ end
+
+ add_foreign_key :report_notes, :reports, column: :report_id, on_delete: :cascade
+ add_foreign_key :report_notes, :accounts, column: :account_id, on_delete: :cascade
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 18c61dbe0..a9733a2ae 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20180310000000) do
+ActiveRecord::Schema.define(version: 20180402040909) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -355,6 +355,16 @@ ActiveRecord::Schema.define(version: 20180310000000) do
t.index ["status_id", "preview_card_id"], name: "index_preview_cards_statuses_on_status_id_and_preview_card_id"
end
+ create_table "report_notes", force: :cascade do |t|
+ t.text "content", null: false
+ t.bigint "report_id", null: false
+ t.bigint "account_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["account_id"], name: "index_report_notes_on_account_id"
+ t.index ["report_id"], name: "index_report_notes_on_report_id"
+ end
+
create_table "reports", force: :cascade do |t|
t.bigint "status_ids", default: [], null: false, array: true
t.text "comment", default: "", null: false
@@ -364,6 +374,7 @@ ActiveRecord::Schema.define(version: 20180310000000) do
t.bigint "account_id", null: false
t.bigint "action_taken_by_account_id"
t.bigint "target_account_id", null: false
+ t.bigint "assigned_account_id"
t.index ["account_id"], name: "index_reports_on_account_id"
t.index ["target_account_id"], name: "index_reports_on_target_account_id"
end
@@ -569,7 +580,10 @@ ActiveRecord::Schema.define(version: 20180310000000) do
add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id", name: "fk_f5fc4c1ee3", on_delete: :cascade
add_foreign_key "oauth_access_tokens", "users", column: "resource_owner_id", name: "fk_e84df68546", on_delete: :cascade
add_foreign_key "oauth_applications", "users", column: "owner_id", name: "fk_b0988c7c0a", on_delete: :cascade
+ add_foreign_key "report_notes", "accounts", on_delete: :cascade
+ add_foreign_key "report_notes", "reports", on_delete: :cascade
add_foreign_key "reports", "accounts", column: "action_taken_by_account_id", name: "fk_bca45b75fd", on_delete: :nullify
+ add_foreign_key "reports", "accounts", column: "assigned_account_id", on_delete: :nullify
add_foreign_key "reports", "accounts", column: "target_account_id", name: "fk_eb37af34f0", on_delete: :cascade
add_foreign_key "reports", "accounts", name: "fk_4b81f7522c", on_delete: :cascade
add_foreign_key "session_activations", "oauth_access_tokens", column: "access_token_id", name: "fk_957e5bda89", on_delete: :cascade
diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb
index 71a185147..9be298df6 100644
--- a/spec/controllers/admin/reports_controller_spec.rb
+++ b/spec/controllers/admin/reports_controller_spec.rb
@@ -61,7 +61,7 @@ describe Admin::ReportsController do
report = Fabricate(:report)
put :update, params: { id: report, outcome: 'resolve' }
- expect(response).to redirect_to(admin_report_path(report))
+ expect(response).to redirect_to(admin_reports_path)
report.reload
expect(report.action_taken_by_account).to eq user.account
expect(report.action_taken).to eq true
@@ -74,7 +74,7 @@ describe Admin::ReportsController do
allow(Admin::SuspensionWorker).to receive(:perform_async)
put :update, params: { id: report, outcome: 'suspend' }
- expect(response).to redirect_to(admin_report_path(report))
+ expect(response).to redirect_to(admin_reports_path)
report.reload
expect(report.action_taken_by_account).to eq user.account
expect(report.action_taken).to eq true
@@ -88,12 +88,46 @@ describe Admin::ReportsController do
report = Fabricate(:report)
put :update, params: { id: report, outcome: 'silence' }
- expect(response).to redirect_to(admin_report_path(report))
+ expect(response).to redirect_to(admin_reports_path)
report.reload
expect(report.action_taken_by_account).to eq user.account
expect(report.action_taken).to eq true
expect(report.target_account).to be_silenced
end
end
+
+ describe 'with an outsome of `reopen`' do
+ it 'reopens the report' do
+ report = Fabricate(:report)
+
+ put :update, params: { id: report, outcome: 'reopen' }
+ expect(response).to redirect_to(admin_report_path(report))
+ report.reload
+ expect(report.action_taken_by_account).to eq nil
+ expect(report.action_taken).to eq false
+ end
+ end
+
+ describe 'with an outsome of `assign_to_self`' do
+ it 'reopens the report' do
+ report = Fabricate(:report)
+
+ put :update, params: { id: report, outcome: 'assign_to_self' }
+ expect(response).to redirect_to(admin_report_path(report))
+ report.reload
+ expect(report.assigned_account).to eq user.account
+ end
+ end
+
+ describe 'with an outsome of `unassign`' do
+ it 'reopens the report' do
+ report = Fabricate(:report)
+
+ put :update, params: { id: report, outcome: 'unassign' }
+ expect(response).to redirect_to(admin_report_path(report))
+ report.reload
+ expect(report.assigned_account).to eq nil
+ end
+ end
end
end
From 1c293086a16fce465d5bdc123809f2d28b3e2ab6 Mon Sep 17 00:00:00 2001
From: mayaeh
Date: Tue, 3 Apr 2018 18:21:33 +0900
Subject: [PATCH 035/442] i18n: Add Japanese translations for #7000 (#7022)
* run yarn manage:translations.
* run i18n-tasks add-missing ja.
* Update Japanese translations.
---
.../mastodon/locales/defaultMessages.json | 13 +++++++++++
config/locales/ja.yml | 23 +++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 4c9401deb..5059fc67b 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -1,4 +1,17 @@
[
+ {
+ "descriptors": [
+ {
+ "defaultMessage": "Oops!",
+ "id": "alert.unexpected.title"
+ },
+ {
+ "defaultMessage": "An unexpected error occurred.",
+ "id": "alert.unexpected.message"
+ }
+ ],
+ "path": "app/javascript/mastodon/actions/alerts.json"
+ },
{
"descriptors": [
{
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 090b080e4..629d688c9 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -60,6 +60,7 @@ ja:
destroyed_msg: モデレーションメモを削除しました!
accounts:
are_you_sure: 本当に実行しますか?
+ avatar: アイコン
by_domain: ドメイン
confirm: 確認
confirmed: 確認済み
@@ -108,6 +109,7 @@ ja:
public: パブリック
push_subscription_expires: PuSH購読期限
redownload: アバターの更新
+ remove_avatar: アイコンを削除
reset: リセット
reset_password: パスワード再設定
resubscribe: 再講読
@@ -135,6 +137,7 @@ ja:
web: Web
action_logs:
actions:
+ assigned_to_self_report: "%{name} さんがレポート %{target} を自身の担当に割り当てました"
confirm_user: "%{name} さんが %{target} さんのメールアドレスを確認済みにしました"
create_custom_emoji: "%{name} さんがカスタム絵文字 %{target} を追加しました"
create_domain_block: "%{name} さんがドメイン %{target} をブロックしました"
@@ -150,10 +153,13 @@ ja:
enable_user: "%{name} さんが %{target} さんのログインを有効化しました"
memorialize_account: "%{name} さんが %{target} さんを追悼アカウントページに登録しました"
promote_user: "%{name} さんが %{target} さんを昇格しました"
+ remove_avatar_user: "%{name} さんが %{target} さんのアイコンを削除しました"
+ reopen_report: "%{name} さんがレポート %{target} を再び開きました"
reset_password_user: "%{name} さんが %{target} さんのパスワードをリセットしました"
resolve_report: "%{name} さんがレポート %{target} を解決済みにしました"
silence_account: "%{name} さんが %{target} さんをサイレンスにしました"
suspend_account: "%{name} さんが %{target} さんを停止しました"
+ unassigned_report: "%{name} さんがレポート %{target} の担当を外しました"
unsilence_account: "%{name} さんが %{target} さんのサイレンスを解除しました"
unsuspend_account: "%{name} さんが %{target} さんの停止を解除しました"
update_custom_emoji: "%{name} さんがカスタム絵文字 %{target} を更新しました"
@@ -239,29 +245,45 @@ ja:
expired: 期限切れ
title: フィルター
title: 招待
+ report_notes:
+ created_msg: モデレーションメモを書き込みました!
+ destroyed_msg: モデレーションメモを削除しました!
reports:
action_taken_by: レポート処理者
are_you_sure: 本当に実行しますか?
+ assign_to_self: 担当になる
+ assigned: 担当者
comment:
label: コメント
none: なし
delete: 削除
id: ID
mark_as_resolved: 解決済みとしてマーク
+ mark_as_unresolved: 未解決として再び開く
+ notes:
+ create: 書き込む
+ create_and_resolve: 書き込み、解決済みにする
+ delete: 削除
+ label: メモ
nsfw:
'false': NSFW オフ
'true': NSFW オン
+ reopen: 再び開く
report: レポート#%{id}
report_contents: 内容
reported_account: 報告対象アカウント
reported_by: 報告者
resolved: 解決済み
+ resolved_msg: レポートを解決済みにしました!
silence_account: アカウントをサイレンス
status: ステータス
+ statuses: 通報されたトゥート
suspend_account: アカウントを停止
target: ターゲット
title: レポート
+ unassign: 担当を外す
unresolved: 未解決
+ updated_at: 更新日時
view: 表示
settings:
activity_api_enabled:
@@ -475,6 +497,7 @@ ja:
'21600': 6 時間
'3600': 1 時間
'43200': 12 時間
+ '604800': 1 週間
'86400': 1 日
expires_in_prompt: 無期限
generate: 作成
From 2e59751823585a8ef8729d4287239b326ab02193 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Tue, 3 Apr 2018 13:07:32 +0200
Subject: [PATCH 036/442] Improve require_admin! and require_staff! filters
(#7018)
Previously these returns 302 redirects instead of 403s, which meant posting links to admin pages in slack caused them to unfurl, rather than stay as a link. Additionally, require_admin! doesn't appear to be actively used, on require_staff!
---
app/controllers/application_controller.rb | 4 +-
.../controllers/admin/base_controller_spec.rb | 25 +++++++----
.../application_controller_spec.rb | 42 ++++++++++++++++++-
3 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 6e5042617..588526447 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -39,11 +39,11 @@ class ApplicationController < ActionController::Base
end
def require_admin!
- redirect_to root_path unless current_user&.admin?
+ forbidden unless current_user&.admin?
end
def require_staff!
- redirect_to root_path unless current_user&.staff?
+ forbidden unless current_user&.staff?
end
def check_suspension
diff --git a/spec/controllers/admin/base_controller_spec.rb b/spec/controllers/admin/base_controller_spec.rb
index 2b60e7e92..9ac833623 100644
--- a/spec/controllers/admin/base_controller_spec.rb
+++ b/spec/controllers/admin/base_controller_spec.rb
@@ -9,18 +9,25 @@ describe Admin::BaseController, type: :controller do
end
end
- it 'renders admin layout' do
+ it 'requires administrator or moderator' do
+ routes.draw { get 'success' => 'admin/base#success' }
+ sign_in(Fabricate(:user, admin: false, moderator: false))
+ get :success
+
+ expect(response).to have_http_status(:forbidden)
+ end
+
+ it 'renders admin layout as a moderator' do
+ routes.draw { get 'success' => 'admin/base#success' }
+ sign_in(Fabricate(:user, moderator: true))
+ get :success
+ expect(response).to render_template layout: 'admin'
+ end
+
+ it 'renders admin layout as an admin' do
routes.draw { get 'success' => 'admin/base#success' }
sign_in(Fabricate(:user, admin: true))
get :success
expect(response).to render_template layout: 'admin'
end
-
- it 'requires administrator' do
- routes.draw { get 'success' => 'admin/base#success' }
- sign_in(Fabricate(:user, admin: false))
- get :success
-
- expect(response).to redirect_to('/')
- end
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 51c0e3c70..3e4d27e05 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -181,10 +181,48 @@ describe ApplicationController, type: :controller do
routes.draw { get 'sucesss' => 'anonymous#sucesss' }
end
- it 'redirects to root path if current user is not admin' do
+ it 'returns a 403 if current user is not admin' do
sign_in(Fabricate(:user, admin: false))
get 'sucesss'
- expect(response).to redirect_to('/')
+ expect(response).to have_http_status(403)
+ end
+
+ it 'returns a 403 if current user is only a moderator' do
+ sign_in(Fabricate(:user, moderator: true))
+ get 'sucesss'
+ expect(response).to have_http_status(403)
+ end
+
+ it 'does nothing if current user is admin' do
+ sign_in(Fabricate(:user, admin: true))
+ get 'sucesss'
+ expect(response).to have_http_status(200)
+ end
+ end
+
+ describe 'require_staff!' do
+ controller do
+ before_action :require_staff!
+
+ def sucesss
+ head 200
+ end
+ end
+
+ before do
+ routes.draw { get 'sucesss' => 'anonymous#sucesss' }
+ end
+
+ it 'returns a 403 if current user is not admin or moderator' do
+ sign_in(Fabricate(:user, admin: false, moderator: false))
+ get 'sucesss'
+ expect(response).to have_http_status(403)
+ end
+
+ it 'does nothing if current user is moderator' do
+ sign_in(Fabricate(:user, moderator: true))
+ get 'sucesss'
+ expect(response).to have_http_status(200)
end
it 'does nothing if current user is admin' do
From 6ff3b3e4db09c8ddf2faad6710e4a25f988e762d Mon Sep 17 00:00:00 2001
From: Nolan Lawson
Date: Tue, 3 Apr 2018 04:08:11 -0700
Subject: [PATCH 037/442] Fix nil account issue in ProcessAccountService
(#7019)
---
app/services/activitypub/process_account_service.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index cf8462821..21c2fc57a 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -28,7 +28,7 @@ class ActivityPub::ProcessAccountService < BaseService
after_protocol_change! if protocol_changed?
after_key_change! if key_changed?
- check_featured_collection! if @account.featured_collection_url.present?
+ check_featured_collection! if @account&.featured_collection_url&.present?
@account
rescue Oj::ParseError
From d8d42179590db772cc5b1873385cba7e5afe20df Mon Sep 17 00:00:00 2001
From: ThibG
Date: Tue, 3 Apr 2018 21:09:14 +0200
Subject: [PATCH 038/442] Fix french wording of reblogged toots in public
views, matching the wording of reblogged_by (#7029)
---
config/locales/fr.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 6137e1bd4..d7371dc94 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -661,7 +661,7 @@ fr:
stream_entries:
click_to_show: Cliquer pour afficher
pinned: Pouet épinglé
- reblogged: partagé
+ reblogged: a partagé
sensitive_content: Contenu sensible
terms:
body_html: |
From 07176fed374b0ef94aacd1f3ea95b6dec2eb79dd Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Wed, 4 Apr 2018 01:11:26 +0200
Subject: [PATCH 039/442] Add contact account to landing page ("Administered
by") (#6984)
---
app/javascript/styles/mastodon/about.scss | 48 +++++++++++++++++++++++
app/views/about/show.html.haml | 22 +++++++++++
config/locales/en.yml | 1 +
spec/views/about/show.html.haml_spec.rb | 1 +
4 files changed, 72 insertions(+)
diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss
index c484f074b..03211036c 100644
--- a/app/javascript/styles/mastodon/about.scss
+++ b/app/javascript/styles/mastodon/about.scss
@@ -681,6 +681,54 @@ $small-breakpoint: 960px;
margin-bottom: 0;
}
+ .account {
+ border-bottom: 0;
+ padding: 0;
+
+ &__display-name {
+ align-items: center;
+ display: flex;
+ margin-right: 5px;
+ }
+
+ div.account__display-name {
+ &:hover {
+ .display-name strong {
+ text-decoration: none;
+ }
+ }
+
+ .account__avatar {
+ cursor: default;
+ }
+ }
+
+ &__avatar-wrapper {
+ margin-left: 0;
+ flex: 0 0 auto;
+ }
+
+ &__avatar {
+ width: 44px;
+ height: 44px;
+ background-size: 44px 44px;
+ }
+
+ .display-name {
+ font-size: 15px;
+
+ &__account {
+ font-size: 14px;
+ }
+ }
+ }
+
+ @media screen and (max-width: $small-breakpoint) {
+ .contact {
+ margin-top: 30px;
+ }
+ }
+
@media screen and (max-width: $column-breakpoint) {
padding: 25px 20px;
}
diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml
index 85e5442af..12213cda2 100644
--- a/app/views/about/show.html.haml
+++ b/app/views/about/show.html.haml
@@ -108,6 +108,28 @@
%div
%h3= t 'about.what_is_mastodon'
%p= t 'about.about_mastodon_html'
+ %div.contact
+ %h3= t 'about.administered_by'
+
+ .account
+ .account__wrapper
+ - if @instance_presenter.contact_account
+ = link_to TagManager.instance.url_for(@instance_presenter.contact_account), class: 'account__display-name' do
+ .account__avatar-wrapper
+ .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" }
+ %span.display-name
+ %bdi
+ %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account)
+ %span.display-name__account @#{@instance_presenter.contact_account.acct}
+ - else
+ .account__display-name
+ .account__avatar-wrapper
+ .account__avatar{ style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})" }
+ %span.display-name
+ %strong= t 'about.contact_missing'
+ %span.display-name__account= t 'about.contact_unavailable'
+
+ = link_to t('about.learn_more'), about_more_path, class: 'button button-alternative'
= render 'features'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 51d9c906d..945faa1e2 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -4,6 +4,7 @@ en:
about_hashtag_html: These are public toots tagged with #%{hashtag}. You can interact with them if you have an account anywhere in the fediverse.
about_mastodon_html: Mastodon is a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.
about_this: About
+ administered_by: 'Administered by:'
closed_registrations: Registrations are currently closed on this instance. However! You can find a different instance to make an account on and get access to the very same network from there.
contact: Contact
contact_missing: Not set
diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb
index 03d6fb7ab..cbe5aa93b 100644
--- a/spec/views/about/show.html.haml_spec.rb
+++ b/spec/views/about/show.html.haml_spec.rb
@@ -19,6 +19,7 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do
hero: nil,
user_count: 0,
status_count: 0,
+ contact_account: nil,
closed_registrations_message: 'yes')
assign(:instance_presenter, instance_presenter)
render
From 7a810827040f31fb3936047f444efb77b743ed85 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Wed, 4 Apr 2018 11:58:15 +0200
Subject: [PATCH 040/442] Revert "Add double-tap zoom functionary to
`ZoomableImage` (#6944)" (#7035)
Unfortunately the new hammer.js functionality wasn't correctly tested and didn't work across devices and browsers, as such, it's best to revert PR #6944 until we can revisit this functionality and make it work across all devices and browsers that are supported by Mastodon.
This reverts commit 5021c4e9ca78881f5379a18185a46e580b8f2c34.
---
.../features/ui/components/zoomable_image.js | 167 ++++++++----------
.../styles/mastodon/components.scss | 3 +
package.json | 1 -
yarn.lock | 4 -
4 files changed, 76 insertions(+), 99 deletions(-)
diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.js b/app/javascript/mastodon/features/ui/components/zoomable_image.js
index 0cae0862d..0a0a4d41a 100644
--- a/app/javascript/mastodon/features/ui/components/zoomable_image.js
+++ b/app/javascript/mastodon/features/ui/components/zoomable_image.js
@@ -1,10 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
-import Hammer from 'hammerjs';
const MIN_SCALE = 1;
const MAX_SCALE = 4;
-const DOUBLE_TAP_SCALE = 2;
+
+const getMidpoint = (p1, p2) => ({
+ x: (p1.clientX + p2.clientX) / 2,
+ y: (p1.clientY + p2.clientY) / 2,
+});
+
+const getDistance = (p1, p2) =>
+ Math.sqrt(Math.pow(p1.clientX - p2.clientX, 2) + Math.pow(p1.clientY - p2.clientY, 2));
const clamp = (min, max, value) => Math.min(max, Math.max(min, value));
@@ -31,97 +37,83 @@ export default class ZoomableImage extends React.PureComponent {
removers = [];
container = null;
image = null;
- lastScale = null;
- zoomCenter = null;
+ lastTouchEndTime = 0;
+ lastDistance = 0;
componentDidMount () {
- // register pinch event handlers to the container
- let hammer = new Hammer.Manager(this.container, {
- // required to make container scrollable by touch
- touchAction: 'pan-x pan-y',
- });
- hammer.add(new Hammer.Pinch());
- hammer.on('pinchstart', this.handlePinchStart);
- hammer.on('pinchmove', this.handlePinchMove);
- this.removers.push(() => hammer.off('pinchstart pinchmove'));
-
- // register tap event handlers
- hammer = new Hammer.Manager(this.image);
- // NOTE the order of adding is also the order of gesture recognition
- hammer.add(new Hammer.Tap({ event: 'doubletap', taps: 2 }));
- hammer.add(new Hammer.Tap());
- // prevent the 'tap' event handler be fired on double tap
- hammer.get('tap').requireFailure('doubletap');
- // NOTE 'tap' and 'doubletap' events are fired by touch and *mouse*
- hammer.on('tap', this.handleTap);
- hammer.on('doubletap', this.handleDoubleTap);
- this.removers.push(() => hammer.off('tap doubletap'));
+ let handler = this.handleTouchStart;
+ this.container.addEventListener('touchstart', handler);
+ this.removers.push(() => this.container.removeEventListener('touchstart', handler));
+ handler = this.handleTouchMove;
+ // on Chrome 56+, touch event listeners will default to passive
+ // https://www.chromestatus.com/features/5093566007214080
+ this.container.addEventListener('touchmove', handler, { passive: false });
+ this.removers.push(() => this.container.removeEventListener('touchend', handler));
}
componentWillUnmount () {
this.removeEventListeners();
}
- componentDidUpdate (prevProps, prevState) {
- if (!this.zoomCenter) return;
-
- const { x: cx, y: cy } = this.zoomCenter;
- const { scale: prevScale } = prevState;
- const { scale: nextScale } = this.state;
- const { scrollLeft, scrollTop } = this.container;
-
- // math memo:
- // x = (scrollLeft + cx) / scrollWidth
- // x' = (nextScrollLeft + cx) / nextScrollWidth
- // scrollWidth = clientWidth * prevScale
- // scrollWidth' = clientWidth * nextScale
- // Solve x = x' for nextScrollLeft
- const nextScrollLeft = (scrollLeft + cx) * nextScale / prevScale - cx;
- const nextScrollTop = (scrollTop + cy) * nextScale / prevScale - cy;
-
- this.container.scrollLeft = nextScrollLeft;
- this.container.scrollTop = nextScrollTop;
- }
-
removeEventListeners () {
this.removers.forEach(listeners => listeners());
this.removers = [];
}
- handleClick = e => {
- // prevent the click event propagated to parent
+ handleTouchStart = e => {
+ if (e.touches.length !== 2) return;
+
+ this.lastDistance = getDistance(...e.touches);
+ }
+
+ handleTouchMove = e => {
+ const { scrollTop, scrollHeight, clientHeight } = this.container;
+ if (e.touches.length === 1 && scrollTop !== scrollHeight - clientHeight) {
+ // prevent propagating event to MediaModal
+ e.stopPropagation();
+ return;
+ }
+ if (e.touches.length !== 2) return;
+
+ e.preventDefault();
e.stopPropagation();
- // the tap event handler is executed at the same time by touch and mouse,
- // so we don't need to execute the onClick handler here
+ const distance = getDistance(...e.touches);
+ const midpoint = getMidpoint(...e.touches);
+ const scale = clamp(MIN_SCALE, MAX_SCALE, this.state.scale * distance / this.lastDistance);
+
+ this.zoom(scale, midpoint);
+
+ this.lastMidpoint = midpoint;
+ this.lastDistance = distance;
}
- handlePinchStart = () => {
- this.lastScale = this.state.scale;
+ zoom(nextScale, midpoint) {
+ const { scale } = this.state;
+ const { scrollLeft, scrollTop } = this.container;
+
+ // math memo:
+ // x = (scrollLeft + midpoint.x) / scrollWidth
+ // x' = (nextScrollLeft + midpoint.x) / nextScrollWidth
+ // scrollWidth = clientWidth * scale
+ // scrollWidth' = clientWidth * nextScale
+ // Solve x = x' for nextScrollLeft
+ const nextScrollLeft = (scrollLeft + midpoint.x) * nextScale / scale - midpoint.x;
+ const nextScrollTop = (scrollTop + midpoint.y) * nextScale / scale - midpoint.y;
+
+ this.setState({ scale: nextScale }, () => {
+ this.container.scrollLeft = nextScrollLeft;
+ this.container.scrollTop = nextScrollTop;
+ });
}
- handlePinchMove = e => {
- const scale = clamp(MIN_SCALE, MAX_SCALE, this.lastScale * e.scale);
- this.zoom(scale, e.center);
- }
-
- handleTap = () => {
+ handleClick = e => {
+ // don't propagate event to MediaModal
+ e.stopPropagation();
const handler = this.props.onClick;
if (handler) handler();
}
- handleDoubleTap = e => {
- if (this.state.scale === MIN_SCALE)
- this.zoom(DOUBLE_TAP_SCALE, e.center);
- else
- this.zoom(MIN_SCALE, e.center);
- }
-
- zoom (scale, center) {
- this.zoomCenter = center;
- this.setState({ scale });
- }
-
setContainerRef = c => {
this.container = c;
}
@@ -134,18 +126,6 @@ export default class ZoomableImage extends React.PureComponent {
const { alt, src } = this.props;
const { scale } = this.state;
const overflow = scale === 1 ? 'hidden' : 'scroll';
- const marginStyle = {
- position: 'absolute',
- top: 0,
- bottom: 0,
- left: 0,
- right: 0,
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- transform: `scale(${scale})`,
- transformOrigin: '0 0',
- };
return (
-
-
-
+
);
}
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 6a83be452..d76dc10f1 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -1483,6 +1483,9 @@
position: relative;
width: 100%;
height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
img {
max-width: $media-modal-media-max-width;
diff --git a/package.json b/package.json
index d4de3a157..9858d28d4 100644
--- a/package.json
+++ b/package.json
@@ -54,7 +54,6 @@
"file-loader": "^0.11.2",
"font-awesome": "^4.7.0",
"glob": "^7.1.1",
- "hammerjs": "^2.0.8",
"http-link-header": "^0.8.0",
"immutable": "^3.8.2",
"imports-loader": "^0.8.0",
diff --git a/yarn.lock b/yarn.lock
index 866b24c7a..fba2cb9a7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3096,10 +3096,6 @@ gzip-size@^3.0.0:
dependencies:
duplexer "^0.1.1"
-hammerjs@^2.0.8:
- version "2.0.8"
- resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1"
-
handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
From 1c1042556d21e4c2eb22b7c5cbc11aa88087ca60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?=
Date: Wed, 4 Apr 2018 20:13:43 +0200
Subject: [PATCH 041/442] i18n: Update Polish translation (#7037)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* i18n: Update Polish translation
Signed-off-by: Marcin Mikołajczak
* i18n: Update Polish translation
Signed-off-by: Marcin Mikołajczak
---
config/locales/pl.yml | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index e92742ef4..c62636081 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -4,6 +4,7 @@ pl:
about_hashtag_html: Znajdują się tu publiczne wpisy oznaczone hashtagiem #%{hashtag}. Możesz dołączyć do dyskusji, jeżeli posiadasz konto gdziekolwiek w Fediwersum.
about_mastodon_html: Mastodon jest wolną i otwartą siecią społecznościową, zdecentralizowaną alternatywą dla zamkniętych, komercyjnych platform.
about_this: O tej instancji
+ administered_by: 'Administrowana przez:'
closed_registrations: Rejestracja na tej instancji jest obecnie zamknięta. Możesz jednak zarejestrować się na innej instancji, uzyskując dostęp do tej samej sieci.
contact: Kontakt
contact_missing: Nie ustawiono
@@ -60,6 +61,7 @@ pl:
destroyed_msg: Pomyślnie usunięto notatkę moderacyjną!
accounts:
are_you_sure: Jesteś tego pewien?
+ avatar: Awatar
by_domain: Domena
confirm: Potwierdź
confirmed: Potwierdzono
@@ -108,6 +110,7 @@ pl:
public: Publiczne
push_subscription_expires: Subskrypcja PuSH wygasa
redownload: Odśwież awatar
+ remove_avatar: Usun awatar
reset: Resetuj
reset_password: Resetuj hasło
resubscribe: Ponów subskrypcję
@@ -135,6 +138,7 @@ pl:
web: Sieć
action_logs:
actions:
+ assigned_to_self_report: "%{name} przypisał sobie zgłoszenie %{target}"
confirm_user: "%{name} potwierdził adres e-mail użytkownika %{target}"
create_custom_emoji: "%{name} dodał nowe emoji %{target}"
create_domain_block: "%{name} zablokował domenę %{target}"
@@ -150,10 +154,13 @@ pl:
enable_user: "%{name} przywrócił możliwość logowania użytkownikowi %{target}"
memorialize_account: "%{name} nadał kontu %{target} status in memoriam"
promote_user: "%{name} podniósł uprawnienia użytkownikowi %{target}"
+ remove_avatar_user: "%{name} usunął awatar użytkownikowi %{target}"
+ reopen_report: "%{name} otworzył ponownie zgłoszenie %{target}"
reset_password_user: "%{name} przywrócił hasło użytkownikowi %{target}"
- resolve_report: "%{name} odrzucił zgłoszenie %{target}"
+ resolve_report: "%{name} rozwiązał zgłoszenie %{target}"
silence_account: "%{name} wyciszył konto %{target}"
suspend_account: "%{name} zawiesił konto %{target}"
+ unassigned_report: "%{name} cofnął przypisanie zgłoszenia %{target}"
unsilence_account: "%{name} cofnął wyciszenie konta %{target}"
unsuspend_account: "%{name} cofnął zawieszenie konta %{target}"
update_custom_emoji: "%{name} zaktualizował emoji %{target}"
@@ -240,15 +247,26 @@ pl:
expired: Wygasłe
title: Filtruj
title: Zaproszenia
+ report_notes:
+ created_msg: Pomyslnie utworzono notatkę moderacyjną.
+ destroyed_msg: Pomyślnie usunięto notatkę moderacyjną.
reports:
action_taken_by: Działanie podjęte przez
are_you_sure: Czy na pewno?
+ assign_to_self: Przypisz do siebie
+ assigned: Przypisany moderator
comment:
- label: Komentarz
+ label: Komentarz do zgłoszenia
none: Brak
delete: Usuń
id: ID
mark_as_resolved: Oznacz jako rozwiązane
+ mark_as_unresolved: Oznacz jako nierozwiązane
+ notes:
+ create: Utwórz notatkę
+ create_and_resolve: Rozwiąż i pozostaw notatkę
+ delete: Usuń
+ label: Notatki
nsfw:
'false': Nie oznaczaj jako NSFW
'true': Oznaczaj jako NSFW
@@ -257,12 +275,16 @@ pl:
reported_account: Zgłoszone konto
reported_by: Zgłaszający
resolved: Rozwiązane
+ resolved_msg: Pomyślnie rozwiązano zgłoszenie.
silence_account: Wycisz konto
status: Stan
+ statuses: Zgłoszone wpisy
suspend_account: Zawieś konto
target: Cel
title: Zgłoszenia
+ unassign: Cofnij przypisanie
unresolved: Nierozwiązane
+ updated_at: Zaktualizowano
view: Wyświetl
settings:
activity_api_enabled:
From f1867a73881444dfed9e093425435681ee764922 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Wed, 4 Apr 2018 21:47:39 +0200
Subject: [PATCH 042/442] Adjust privacy policy (#6666)
* Adjust privacy policy to be more specific to Mastodon
Fix #6613
* Change data retention of IP addresses from 5 years to 1 year
* Add even more information
* Remove all (now invalid) translations of the privacy policy
* Add information about archive takeout, remove pointless consent section
* Emphasis on DM privacy
* Improve wording
* Add line about data use for moderation purposes
---
app/javascript/styles/mastodon/about.scss | 5 ++
app/workers/scheduler/ip_cleanup_scheduler.rb | 4 +-
config/locales/ca.yml | 68 ------------------
config/locales/en.yml | 61 +++++++++-------
config/locales/eo.yml | 68 ------------------
config/locales/es.yml | 68 ------------------
config/locales/fa.yml | 68 ------------------
config/locales/fr.yml | 68 ------------------
config/locales/gl.yml | 68 ------------------
config/locales/hu.yml | 70 -------------------
config/locales/ja.yml | 68 ------------------
config/locales/ko.yml | 68 ------------------
config/locales/nl.yml | 68 ------------------
config/locales/no.yml | 68 ------------------
config/locales/oc.yml | 68 ------------------
config/locales/pl.yml | 68 ------------------
config/locales/pt-BR.yml | 68 ------------------
config/locales/pt.yml | 68 ------------------
config/locales/ru.yml | 39 -----------
config/locales/sr-Latn.yml | 68 ------------------
config/locales/sr.yml | 68 ------------------
config/locales/sv.yml | 68 ------------------
config/locales/zh-CN.yml | 68 ------------------
23 files changed, 43 insertions(+), 1360 deletions(-)
diff --git a/app/javascript/styles/mastodon/about.scss b/app/javascript/styles/mastodon/about.scss
index 03211036c..034c35e8a 100644
--- a/app/javascript/styles/mastodon/about.scss
+++ b/app/javascript/styles/mastodon/about.scss
@@ -322,6 +322,11 @@ $small-breakpoint: 960px;
border: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
margin: 20px 0;
+
+ &.spacer {
+ height: 1px;
+ border: 0;
+ }
}
.container-alt {
diff --git a/app/workers/scheduler/ip_cleanup_scheduler.rb b/app/workers/scheduler/ip_cleanup_scheduler.rb
index 9f1593c91..a33ca031e 100644
--- a/app/workers/scheduler/ip_cleanup_scheduler.rb
+++ b/app/workers/scheduler/ip_cleanup_scheduler.rb
@@ -4,8 +4,10 @@ require 'sidekiq-scheduler'
class Scheduler::IpCleanupScheduler
include Sidekiq::Worker
+ RETENTION_PERIOD = 1.year
+
def perform
- time_ago = 5.years.ago
+ time_ago = RETENTION_PERIOD.ago
SessionActivation.where('updated_at < ?', time_ago).destroy_all
User.where('last_sign_in_at < ?', time_ago).update_all(last_sign_in_ip: nil)
end
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index 7727bad37..fc30b3661 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -665,74 +665,6 @@ ca:
reblogged: ha impulsat
sensitive_content: Contingut sensible
terms:
- body_html: |
-
Política de privacitat
-
-
Quina informació recollim?
-
-
Recopilem informació teva quan et registres en aquesta instància i recopilem dades quan participes en el fòrum llegint, escrivint i avaluant el contingut aquí compartit.
-
-
En registrar-te en aquesta instància, se't pot demanar que introduexis el teu nom i l'adreça de correu electrònic. També pots visitar el nostre lloc sense registrar-te. La teva adreça de correu electrònic es verificarà mitjançant un correu electrònic que conté un enllaç únic. Si es visita aquest enllaç, sabem que controles l'adreça de correu electrònic.
-
-
Quan es registra i publica, registrem l'adreça IP de la qual es va originar la publicació. També podrem conservar els registres del servidor que inclouen l'adreça IP de cada sol·licitud al nostre servidor.
-
-
Per a què utilitzem la teva informació?
-
-
Qualsevol de la informació que recopilem de tu pot utilitzar-se d'una de les maneres següents:
-
-
-
Per a personalitzar la teva experiència — la teva informació ens ajuda a respondre millor a les teves necessitats individuals.
-
Per millorar el nostre lloc — ens esforcem contínuament per millorar les nostres ofertes de llocs basats en la informació i els comentaris que rebem de tu.
-
Per millorar el servei al client — la teva informació ens ajuda a respondre més eficaçment a les teves sol·licituds de servei al client i a les necessitats de suport.
-
Per enviar correus electrònics periòdics — l'adreça electrònica que proporcionis es pot utilitzar per enviar-te informació, notificacions que sol·licitis sobre canvis en temes o en resposta al teu nom d'usuari, respondre a les consultes i/o altres sol·licituds o preguntes.
-
-
-
Com protegim la teva informació?
-
-
Implementem diverses mesures de seguretat per mantenir la seguretat de la teva informació personal quan introdueixes, envies o accedeixes a la teva informació personal.
-
-
Quina és la nostre política de retenció de dades?
-
-
Farem un esforç de bona fe per a:
-
-
-
Conserva els registres de servidor que continguin l'adreça IP de totes les sol·licituds a aquest servidor no més de 90 dies.
-
Conserva les adreces IP associades als usuaris registrats i les seves publicacions no més de 5 anys.
-
-
-
Utilitzem galetes?
-
-
Sí. Les cookies són fitxers petits que un lloc o el proveïdor de serveis transfereix al disc dur del vostre ordinador a través del navegador web (si ho permet). Aquestes galetes permeten al lloc reconèixer el vostre navegador i, si teniu un compte registrat, associar-lo al vostre compte registrat.
-
-
Utilitzem cookies per comprendre i desar les vostres preferències per a futures visites i compilar dades agregades sobre el trànsit del lloc i la interacció del lloc, de manera que podrem oferir millors experiències i eines del lloc en el futur. Podem contractar amb proveïdors de serveis de tercers per ajudar-nos a comprendre millor els visitants del nostre lloc. Aquests proveïdors de serveis no estan autoritzats a utilitzar la informació recollida en nom nostre, excepte per ajudar-nos a dur a terme i millorar el nostre negoci.
-
-
Publiquem informació al exterior?
-
-
No venem, comercialitzem ni transmetem a tercers la vostra informació d'identificació personal. Això no inclou tercers de confiança que ens ajudin a operar el nostre lloc, a dur a terme el nostre negoci o a fer-ho, sempre que aquestes parts acceptin mantenir confidencial aquesta informació. També podem publicar la vostra informació quan creiem que l'alliberament és apropiat per complir amb la llei, fer complir les polítiques del nostre lloc o protegir els nostres drets o altres drets, propietat o seguretat. No obstant això, la informació de visitant que no sigui personalment identificable es pot proporcionar a altres parts per a la comercialització, la publicitat o altres usos.
-
-
Vincles de tercers
-
-
De tant en tant, segons el nostre criteri, podem incloure o oferir productes o serveis de tercers al nostre lloc. Aquests llocs de tercers tenen polítiques de privadesa separades i independents. Per tant, no tenim responsabilitat ni responsabilitat civil pel contingut i les activitats d'aquests llocs enllaçats. No obstant això, busquem protegir la integritat del nostre lloc i donem la benvinguda a qualsevol comentari sobre aquests llocs.
-
-
Compliment de la Llei de protecció de la privacitat en línia dels nens
-
-
El nostre lloc, productes i serveis estan dirigits a persones que tenen almenys 13 anys. Si aquest servidor es troba als EUA, i teniu menys de 13 anys, segons els requisits de COPPA (Children's Online Privacy Protection Act) no feu servir aquest lloc.
-
-
Només la política de privacitat en línia
-
-
Aquesta política de privacitat en línia només s'aplica a la informació recopilada a través del nostre lloc i no a la informació recopilada fora de línia.
-
-
El vostre consentiment
-
-
En utilitzar el nostre lloc, accepta la política de privadesa del nostre lloc web.
-
-
Canvis a la nostra política de privacitat
-
-
Si decidim canviar la nostra política de privadesa, publicarem aquests canvis en aquesta pàgina.
-
-
Aquest document és CC-BY-SA. Es va actualitzar per última vegada el 31 de maig de 2013.
title: "%{instance} Condicions del servei i política de privadesa"
themes:
default: Mastodont
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 945faa1e2..70af9530c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -691,70 +691,79 @@ en:
terms:
body_html: |
Privacy Policy
-
What information do we collect?
-
We collect information from you when you register on our site and gather data when you participate in the forum by reading, writing, and evaluating the content shared here.
+
+
Basic account information: If you register on this server, you may be asked to enter a username, an e-mail address and a password. You may also enter additional profile information such as a display name and biography, and upload a profile picture and header image. The username, display name, biography, profile picture and header image are always listed publicly.
+
Posts, following and other public information: The list of people you follow is listed publicly, the same is true for your followers. When you submit a message, the date and time is stored as well as the application you submitted the message from. Messages may contain media attachments, such as pictures and videos. Public and unlisted posts are available publicly. When you feature a post on your profile, that is also publicly available information. Your posts are delivered to your followers, in some cases it means they are delivered to different servers and copies are stored there. When you delete posts, this is likewise delivered to your followers. The action of reblogging or favouriting another post is always public.
+
Direct and followers-only posts: All posts are stored and processed on the server. Followers-only posts are delivered to your followers and users who are mentioned in them, and direct posts are delivered only to users mentioned in them. In some cases it means they are delivered to different servers and copies are stored there. We make a good faith effort to limit the access to those posts only to authorized persons, but other servers may fail to do so. Therefore it's important to review servers your followers belong to. You may toggle an option to approve and reject new followers manually in the settings. Please keep in mind that the operators of the server and any receiving server may view such messages, and that recipients may screenshot, copy or otherwise re-share them. Do not share any dangerous information over Mastodon.
+
IPs and other metadata: When you log in, we record the IP address you log in from, as well as the name of your browser application. All the logged in sessions are available for your review and revocation in the settings. The latest IP address used is stored for up to 12 months. We also may retain server logs which include the IP address of every request to our server.
+
-
When registering on our site, you may be asked to enter your name and e-mail address. You may, however, visit our site without registering. Your e-mail address will be verified by an email containing a unique link. If that link is visited, we know that you control the e-mail address.
-
-
When registered and posting, we record the IP address that the post originated from. We also may retain server logs which include the IP address of every request to our server.
+
What do we use your information for?
-
Any of the information we collect from you may be used in one of the following ways:
+
Any of the information we collect from you may be used in the following ways:
-
To personalize your experience — your information helps us to better respond to your individual needs.
-
To improve our site — we continually strive to improve our site offerings based on the information and feedback we receive from you.
-
To improve customer service — your information helps us to more effectively respond to your customer service requests and support needs.
-
To send periodic emails — The email address you provide may be used to send you information, notifications that you request about changes to topics or in response to your user name, respond to inquiries, and/or other requests or questions.
+
To provide the core functionality of Mastodon. You can only interact with other people's content and post your own content when you are logged in. For example, you may follow other people to view their combined posts in your own personalized home timeline.
+
To aid moderation of the community, for example comparing your IP address with other known ones to determine ban evasion or other violations.
+
The email address you provide may be used to send you information, notifications about other people interacting with your content or sending you messages, and to respond to inquiries, and/or other requests or questions.
+
+
How do we protect your information?
-
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information.
+
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information. Among other things, your browser session, as well as the traffic between your applications and the API, are secured with SSL, and your password is hashed using a strong one-way algorithm. You may enable two-factor authentication to further secure access to your account.
-
What is your data retention policy?
+
+
+
What is our data retention policy?
We will make a good faith effort to:
-
Retain server logs containing the IP address of all requests to this server no more than 90 days.
-
Retain the IP addresses associated with registered users and their posts no more than 5 years.
+
Retain server logs containing the IP address of all requests to this server, in so far as such logs are kept, no more than 90 days.
+
Retain the IP addresses associated with registered users no more than 12 months.
+
You can request and download an archive of your content, including your posts, media attachments, profile picture, and header image.
+
+
You may irreversibly delete your account at any time.
+
+
+
Do we use cookies?
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
-
We use cookies to understand and save your preferences for future visits and compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future. We may contract with third-party service providers to assist us in better understanding our site visitors. These service providers are not permitted to use the information collected on our behalf except to help us conduct and improve our business.
+
We use cookies to understand and save your preferences for future visits.
+
+
Do we disclose any information to outside parties?
-
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety. However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
+
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety.
-
Third party links
+
Your public content may be downloaded by other servers in the network. Your public and followers-only posts are delivered to the servers where your followers reside, and direct messages are delivered to the servers of the recipients, in so far as those followers or recipients reside on a different server than this.
-
Occasionally, at our discretion, we may include or offer third party products or services on our site. These third party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
+
When you authorize an application to use your account, depending on the scope of permissions you approve, it may access your public profile information, your following list, your followers, your lists, all your posts, and your favourites. Applications can never access your e-mail address or password.
Our site, products and services are all directed to people who are at least 13 years old. If this server is in the USA, and you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
-
Online Privacy Policy Only
-
-
This online privacy policy applies only to information collected through our site and not to information collected offline.
-
-
Your Consent
-
-
By using our site, you consent to our web site privacy policy.
+
Changes to our Privacy Policy
If we decide to change our privacy policy, we will post those changes on this page.
-
This document is CC-BY-SA. It was last updated May 31, 2013.
+
This document is CC-BY-SA. It was last updated March 7, 2018.
title: "%{instance} Terms of Service and Privacy Policy"
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index 84d63d831..a896592b0 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -667,74 +667,6 @@ eo:
reblogged: diskonigita
sensitive_content: Tikla enhavo
terms:
- body_html: |
-
Privateca politiko
-
-
Kiujn informojn ni kolektas?
-
-
Ni kolektas informojn de vi, kiam vi registriĝas en nia retejo aŭ partoprenas en la forumo per legado, skribado, kaj traktado de la enhavo diskonigita ĉi tie.
-
-
En registriĝo, ni povas peti al vi vian nomon kaj retadreson. Vi tamen povas viziti nian retejon sen registriĝo. Via retadreso estos validigita per retmesaĝo, kiu enhavos unikan ligilon. Se tiu ligilo estas vizitita, ni scios ke vi regas la retadreson.
-
-
Post registriĝo, ni registras la IP-adreson de tiu, kiu kreas mesaĝon. Ni ankaŭ povas konservi servilan historion, en kiu troviĝas la IP-adreso de ĉiu peto al nia servilo.
-
-
Por kio ni uzas viajn informojn?
-
-
Ajna informo, kiun ni kolektas povas esti uzata por unu el tiuj celoj:
-
-
-
Proprigi vian sperton — viaj informoj helpas nin pli bone respondi al viaj propraj bezonoj.
-
Plibonigi nian retejon — ni daŭre klopodas por plibonigi nian retejon uzante la informojn kaj komentojn, kiujn ni ricevas de vi.
-
Plibonigi nian helpon al klientoj — viaj informoj helpas nin pli bone respondi al klientaj petoj kaj al subtenaj bezonoj.
-
Sendi periodajn retmesaĝojn — La retadreso, kiun vi donas al ni, povas esti uzata por sendi al vi informojn kaj sciigojn, kiujn vi volas ricevi pri ŝanĝoj rilate al apartaj temoj, aŭ responde al via uzantnomo, al petoj kaj al demandoj.
-
-
-
Kiel ni protektas viajn informojn?
-
-
Ni realigis diversajn sekurigajn procedojn por konservi la sekurecon de viaj personaj informoj kiam vi enmetas, sendas, aŭ aliras viajn personajn informojn.
-
-
Kio estas nia politiko pri konservado de datumoj?
-
-
Ni honeste klopodas:
-
-
-
Ne konservi servilan historion, kiu enhavas la IP-adresojn de ĉiuj petoj, dum pli ol 90 tagoj.
-
Ne konservi la IP-adresojn de registritaj uzantoj kaj de iliaj mesaĝoj dum pli ol 5 jaroj.
-
-
-
Ĉu ni uzas kuketojn?
-
-
Jes. Kuketoj estas etaj dosieroj, kiujn retejo aŭ ĝia servo donas al la memoro de via komputilo, per via retumilo (se vi permesas tion). Ĉi tiuj kuketoj ebligas al la retejo rekoni vian retumilon, kaj se vi havas registritan konton, ligas ĝin al via registrita konto.
-
-
Ni uzas kuketojn por kompreni kaj konservi viajn preferojn por postaj vizitoj, kaj kunmeti informojn pri reteja trafiko kaj interago, por ke ni povu doni pli bonan retejan sperton kaj pli bonajn ilojn estonte. Ni povas kontrakti kun eksteraj servoj por helpi nin pli bone kompreni la vizitantojn de la retejo. Ĉi tiuj eksteraj servoj ne rajtas uzi la informojn, kiujn ni kolektis, krom por helpi nin regi kaj plibonigi nian komercon.
-
-
Ĉu ni disdonas informojn al eksteraj personoj?
-
-
Ni ne vendas, interŝanĝas aŭ transdonas al eksteraj personoj viajn persone identigeblajn informojn. Ĉi tio ne inkludas la eksterajn servojn, kiujn ni fidas, kiuj helpas nin funkciigi nian retejon, regi nian komercon, aŭ servi vin, kiom longe tiuj personoj konsentas pri la sekura konservado de ĉi tiuj informoj. Ni ankaŭ povas disdoni viajn informojn, kiam ni pensas ke tio estas nepra por respekti leĝojn, por respektigi la politikojn de nia retejo, aŭ por protekti la rajtojn, posedaĵojn, kaj sekurecon de ni kaj de aliaj. Tamen, informoj de vizitantoj, kiuj ne identigas personojn, povas esti donitaj al eksteraj personoj por merkatado, reklamado, aŭ aliaj uzoj.
-
-
Eksteraj ligiloj
-
-
Foje, laŭ nia elekto, ni povas enmeti aŭ oferti eksterajn produktojn aŭ servojn en nia retejo. Ĉi tiuj eksteraj retejoj havas apartajn kaj sendependajn privatecajn politikojn. Tial, ni havas nek responsojn nek devigojn rilate al la enhavoj kaj agadoj de ĉi tiuj ligitaj retejoj. Tamen, ni celas protekti tiujn, kiuj uzas nian retejon, kaj bonvenigas ajnan komenton pri ĉi tiuj retejoj.
Niaj retejo, produktoj kaj servoj estas por tiuj, kiuj havas almenaŭ 13 jarojn. Se ĉi tiu servilo estas en Usono, kaj vi havas malpli ol 13 jarojn, pro la postuloj de COPPA (Children's Online Privacy Protection Act) ne uzu ĉi tiun retejon.
-
-
Privateca politiko nur rete
-
-
Ĉi tiu privateca politiko validas nur por informoj kolektitaj per nia retejo kaj ne por informoj kolektitaj eksterrete.
-
-
Via konsento
-
-
Per uzado de nia retejo, vi konsentas kun nia reta privateca politiko.
-
-
Ŝanĝoj al nia privateca politiko
-
-
Se ni decidas ŝanĝi nian privatecan politikon, ni afiŝos tiujn ŝanĝojn en ĉi tiu paĝo.
-
-
Ĉi tiu dokumento estas laŭ permeso CC-BY-SA. Ĝi estis laste ĝisdatigita je 2018-02-27.
title: Uzkondiĉoj kaj privateca politiko de %{instance}
themes:
default: Mastodon
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 671f17d33..8e7a766a8 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -656,74 +656,6 @@ es:
reblogged: retooteado
sensitive_content: Contenido sensible
terms:
- body_html: |
-
Políticas de privacidad
-
-
¿Qué información recolectamos?
-
-
Recolectamos información tuya cuando te registras en nuestro sitio y adquirimos datos cuando participas en el foro leyendo, escribiendo, y evaluando el contenido compartido aquí.
-
-
Cuando te registras en nuestro sitio, puede que se te pida tu nombre y dirección de correo electrónico. De todas formas, puedes visitar nuestro sitio sin registrarte. Tu dirección de correo electrónico será verificada por un e-mail conteniendo un enlace único. Si ese enlace es visitado, sabemos que tú controlas esa dirección.
-
-
Cuando te registras y posteas, grabamos la IP de la que se origina esa acción. También puede que retengamos logs del servidor, que incluyen la dirección IP de todos los pedidos a nuestro servidor.
-
-
¿Para qué usamos tu información?
-
-
Toda la información que recolectamos de ti puede usarse en una de las siguientes maneras:
-
-
-
Para personalizar tu experiencia — tu información nos ayuda a responder mejor tus necesidades individuales.
-
Para mejorar nuestro sitio — nos esforzamos continuamente en mejorar nuestras ofertas del sitio basándonos en la información y apoyo que recibimos de ti.
-
Para mejorar el servicio al cliente — tu información nos ayuda a responder más efectivamente al servicio al cliente y otras necesidades.
-
Para enviar e-mails periódicos — la dirección de e-mail que provees puede usarse para enviarte información, notificaciones que pides sobre cambios en tópicos o en respuesta a tu nombre de usuario, responder consultas, y/u otros pedidos o preguntas.
-
-
-
¿Cómo protegemos tu información?
-
-
Implementamos una variedad de medidas de seguridad para mantener a salvo tu información personal cuando entras, publicas, o accesas a ella.
-
-
¿Cuáles son sus políticas de retención de datos?
-
-
Haremos un gran esfuerzo en:
-
-
-
Retener logs del servidor conteniendo la dirección IP de todos los pedidos a este servidor en no más de 90 días.
-
Retener las direcciones IP asociadas con usuarios registrados y sus posts no más de 5 años.
-
-
-
-
-
Sí. Las cookies son pequeños archivos que un sitio web o su proveedor de servicio transfieren al disco duro de tu computadora a través de tu navegador web (si se le permite). Estas cookies permiten al sitio reconocer tu navegador y, si y tienes una cuenta registrada, asociarlo con ella.
-
-
Usamos cookies para entender y guardar tus preferencias para futuras visitas y agregar datos compilados sobre el tráfico del sitio e interacción para que podamos ofrecer una mejor experiencia y herramientas en el futuro. Puede que contratemos con proveedores de servicio de tercera mano para que nos asistan en el mejor entendimiento de nuestros visitantes del sitio. A estos proveedores de servicio no se les permite usar la información recolectada a nuestras espaldas excepto para ayudarnos a conducir y mejorar nuestro trabajo.
-
-
¿Revelamos alguna información a terceras manos?
-
-
No vendemos, intercambiamos, ni de ninguna otra manera transferimos tu información personal identificable a terceras partes. Esto no incluye las terceras manos que nos asisten en operar nuestro sitio, conducción o trabajo, o en servirte, tanto como que éstas acepten en mantener esta información confidencial. Puede que también liberemos tu información cuando creamos que es apropiado para cumplir con la ley, enforzar nuestras políticas del sitio, o proteger la nuestra u otros derechos, propiedad, o seguridad. De todas formas, la información del visitante autorizado no-personal puede proveerse a otras partes por marketing, publicidad, u otros usos.
-
-
Enlaces de terceras partes
-
-
Ocasionalmente, a nuestra discreción, puede que incluyamos u ofrezcamos productos de terceras partes o servicios en nuestro sitio. Estas terceras partes tienen políticas de privacidad separadas e independientes. Por lo tanto no tenemos responsabilidad u obligación por el contenido y actividades de estos sitios enlazados. Sin embargo, buscamos proteger la integridad de nuestro sitio y dar la bienvenida a cualquier ayuda sobre estos sitios.
-
-
Children's Online Privacy Protection Act Compliance (Cumplimiento de la Ley de la Protección Privada en Línea del Niño)
-
-
Nuestro sitio y todos nuestros productos y servicios están dirigidos a gente que tiene al menos 13 años de edad. Si el servidor está alojado en EE.UU, y tienes menos de 13 años, no uses este sitio por los requerimientos del COPPA (Children's Online Privacy Protection Act).
-
-
Solo Políticas de Privacidad en Línea
-
-
Estas políticas de privacidad aplican únicamente a la información recolectada a través de nuestro sitio y no a información recolectada offline.
-
-
Tu Consentimiento
-
-
Al usar nuestro sitio, estás consentido a nuestras políticas de privacidad del sitio.
-
-
Cambios a nuestras Políticas de Privacidad
-
-
Si decidimos cambiar nuestras políticas de privacidad, las publicaremos en esta página.
-
-
Este documento está publicado bajo la licencia CC-BY-SA. Última vez actualizado el 31 de Mayo del 2013.
title: Términos del Servicio y Políticas de Privacidad de %{instance}
themes:
default: Mastodon
diff --git a/config/locales/fa.yml b/config/locales/fa.yml
index 86756c01b..ed25ea8c9 100644
--- a/config/locales/fa.yml
+++ b/config/locales/fa.yml
@@ -613,74 +613,6 @@ fa:
reblogged: بازبوقید
sensitive_content: محتوای حساس
terms:
- body_html: |
-
سیاست رازداری (Privacy Policy)
-
-
ما چه اطلاعاتی را گردآوری میکنیم؟
-
-
این سایت برخی از اطلاعات مربوط به شما را ثبت میکند. این موارد شامل اطلاعات ثبتنامی شماست، و نیز شامل نوشتههایی است که اینجا میخوانید، مینویسید، یا واکنشهایی که به نوشتههای دیگران نشان میدهید.
-
-
وقتی که در این سایت ثبتنام میکنید، ممکن است از شما بخواهیم که نام و نشانی ایمیل خود را وارد کنید. البته بدون ثبتنام نیز میتوان از این سایت بازدید کرد. برای تأیید ایمیل شما، ما یک نشانی اینترنتی یکتا را به آن میفرستیم. اگر آن نشانی را کسی باز کند، ما میفهمیم که آن شما بودهاید و بنابراین نشانی ایمیل متعلق به شماست.
-
-
وقتی که عضو باشید و چیزی بنویسید، ما نشانی اینترنتیای (IP) را که نوشته از آن آمده است ثبت میکنیم. سیاههٔ کاری (log) سرور شامل نشانی IP همهٔ درخواستها به سرور است که ما شاید آن را هم ثبت کنیم.
-
-
ما با اطلاعات شما چه کار میکنیم؟
-
-
اطلاعاتی را که ما از شما ثبت میکنیم، ممکن است در موارد زیر به کار بروند:
-
-
-
برای شخصیسازی تجربهٔ کاربری شما — ما به کمک اطلاعات شما بهتر میتوانیم نیازهای شما را برآورده کنیم.
-
برای بهتر کردن سایت — ما پیوسته میکوشیم تا خدمات این سایت را به کمک اطلاعات و بازخوردی که از شما میگیریم بهتر کنیم.
-
برای بهتر کردن خدمات به کاربران — ما به کمک اطلاعات شما به طور مؤثرتری میتوانیم به درخواستهای پشتیبانی شما پاسخ دهیم.
-
برای فرستادن ایمیلهای دورهای — ما گاهی به نشانی ایمیلی که وارد کردهاید نامه میفرستیم تا به درخواستهای شما پاسخ دهیم یا شما را در جریان پاسخ دیگران به شما قرار دهیم.
-
-
-
ما چگونه از اطلاعات شما محافظت میکنیم؟
-
-
ما روشهای امنیتی گوناگونی را پیاده کردهایم تا امنیت اطلاعات شخصی شما هنگام ثبت، فرستادهشدن، و بازیابی آنها حفظ شود.
-
-
سیاست ما برای نگهداری اطلاعات شما چیست؟
-
-
ما با حسن نیت تلاش میکنیم تا:
-
-
-
سیاههٔ کاری سرور که شامل نشانی IP همهٔ درخواستها به این سرور است را بیشتر از ۹۰ روز ذخیره نکنیم.
-
نشانی IP مربوط به کاربران ثبتنامشده را بیشتر از ۵ سال نگه نداریم.
-
-
-
آیا ما کوکیها را بهکار میبریم؟
-
-
بله. کوکیها پروندههای کوچکی هستند که یک سایت یا خدماتدهندهاش (اگر شما اجازه بدهید) از راه مرورگر در کامپیوتر شما ذخیره میکنند. به کمک این کوکیها سایت میتواند مرورگر شما را بشناسد و اگر شما ثبتنام کرده باشید، حساب شما را به مرورگرتان مرتبط کند.
-
-
ما به کمک کوکیها ترجیحات شما را برای بازدیدهای آینده میفهمیم و ذخیره میکنیم و دادههای جامعی دربارهٔ بازدیدها از سایت و برهمکنشها با آن را تهیه میکنیم. به این ترتیب میتوانیم در آینده تجربهٔ کاربری سایت و ابزارهای مربوط به آن را بهتر کنیم. برای داشتن درک بهتری از بازدیدکنندگان این سایت، ما گاهی از خدماتدهندههای دیگر نیز کمک میگیریم. این خدماتدهندهها اجازه ندارند تا از اطلاعاتی که به جای ما جمع میکنند برای کاری به جز بهترکردن کار ما استفاده کنند.
-
-
آیا ما اطلاعاتی به نهادهای دیگر فاش میکنیم؟
-
-
ما اطلاعاتی را که بتواند شما را شناسایی کند به نهادهای دیگر نمیفروشیم، معامله نمیکنیم، یا به هر روش دیگری منتقل نمیکنیم. این شامل نهادهای مورد اعتمادی نمیشود که به ما در گرداندن این سایت یا انجام کارهایمان کمک میکنند، یا به شما خدمات میرسانند، تا جایی که آنها این دادهها را محرمانه نگه دارند. ما همچنین ممکن است اطلاعات شما را به حکم قانون یا برای اِعمال سیاستهای سایت، یا به خاطر حفظ حقوق، داراییها، یا امنیت خودمان یا دیگران منتشر کنیم. ما ممکن است اطلاعات بازدیدکنندگان سایت را که با آن نمیتوان شما را شناسایی کرد برای بازاریابی، تبلیغات، یا هدفهای دیگر به نهادهای دیگر ارائه دهیم.
-
-
پیوند (لینک) به صفحههای دیگران
-
-
ما گاهی ممکن است به صلاحدید خودمان محصولات یا خدمات دیگران را در این سایت بگنجانیم یا پیشنهاد دهیم. سایتهای مرتبط با این محصولات و خدمات دارای سیاستهای رازداری جداگانه و مستقل خودشان هستند. بنابراین ما مسئولیتی دربارهٔ محتوا و کنشهای این سایتها به عهده نمیگیریم. با این وجود، ما تلاش میکنیم که این سایت به درستی کار کند و از بازخورد شما برای چنین محصولات و خدماتی استقبال میکنیم.
-
-
پیروی از قانون پشتیبانی از حریم خصوصی آنلاین کودکان
-
-
سایت ما، محصولات و خدماتش همه برای کسانی است که دستکم ۱۳ سال سن داشته باشند. اگر این سرور در خاک ایالات متحدهٔ امریکا قرار دارد و سن شما کمتر از ۱۳ سال است، به خاطر رعایت قانون COPPA (Children's Online Privacy Protection Act) لطفاً این سایت را به کار نبرید.
-
-
تنها سیاست رازداری آنلاین
-
-
این سیاست رازداری آنلاین تنها مربوط به اطلاعاتی است که از راه سایت ما گردآوری میشود و شامل اطلاعاتی که به طور آفلاین گردآوری شده نیست.
-
-
موافقت شما
-
-
با استفاده از این سایت، شما موافقت خود را با سیاست رازداری ما اعلام میکنید.
-
-
تغییرات در سیاست رازداری ما
-
-
اگر ما سیاست رازداری خود را تغییر دهیم، این تغییرات را در این صفحه خواهیم نوشت.
-
-
این نوشته تحت اجازهنامهٔ CC-BY-SA قرار دارد. تاریخ آخرین بهروزرسانی آن ۱۰ خرداد ۱۳۹۲ است.
title: شرایط استفاده و سیاست رازداری %{instance}
themes:
default: ماستدون
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index d7371dc94..4571cc375 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -664,74 +664,6 @@ fr:
reblogged: a partagé
sensitive_content: Contenu sensible
terms:
- body_html: |
-
Politique de confidentialité
-
-
Quelles données collectons-nous ?
-
-
Nous collectons des données lorsque vous vous enregistrez sur notre site et les récoltons lorsque vous participez dans le forum en lisant, écrivant, et évaluant le contenu partagé ici.
-
-
Lors de l’enregistrement sur notre site, il peut vous être demandé de renseigner votre nom et adresse électronique. Vous pouvez, cependant, visiter notre site sans inscription. Votre adresse électronique devra être vérifiée grâce à un courriel contenant un lien unique. Si ce lien est visité, nous savons que vous contrôlez cette adresse.
-
-
Lors de l’inscription et de la publication de statuts, nous enregistrons l’adresse IP de laquelle les statuts proviennent. Nous pouvons également conserver des historiques serveurs qui contiendront l’adresse IP de chaque requête adressée à notre serveur.
-
-
Que faisons-nous avec vos données ?
-
-
Toute information que nous collectons pourra être utilisée d’une des manières suivantes :
-
-
-
Pour personnaliser votre expérience — vos données nous aident à mieux répondre à vos besoins individuels.
-
Pour améliorer notre site — nous faisons tout notre possible pour améliorer notre site en fonction des données, retours et suggestions que nous recevons.
-
Afin d’améliorer le support client — vos données nous aident à mieux répondre à vos requêtes et demandes de support.
-
Afin d’envoyer des courriels à intervalles réguliers — l’adresse électronique que vous renseignez peut être utilisée pour vous envoyer des données et notifications concernant des changements ou en réponse à votre nom d’utilisateur⋅ice, en réponse à vos demandes et/ou autres requêtes ou questions
-
-
-
Comment protégeons-nous vos données ?
-
-
Nous appliquons une multitude de mesures afin de maintenir la sécurité de vos données personnelles lorsque vous entrez, soumettez, ou accédez à ces dernières.
-
-
Quelle est notre politique de conservation des données ?
-
-
Nous nous efforçons de :
-
-
-
ne pas garder les historiques serveurs contenant l’adresse IP de chaque requête adressée à ce serveur plus de 90 jours ;
-
ne pas conserver les adresses IP associées aux utilisateur⋅trices et leur contenu plus de 5 ans.
-
-
-
Utilisons-nous des « cookies » ?
-
-
Oui. Les cookies sont de petits fichiers qu’un site ou prestataires de services transfèrent sur le disque dur de votre ordinateur par le biais de votre navigateur Web (si ce dernier le permet). Ces cookies permettent au site de reconnaître votre navigateur et, si vous disposez d’un compte, de l’associer à celui-ci.
-
-
Nous utilisons les cookies pour enregistrer vos préférences pour de futures visites, compiler des données agrégées à propos du trafic et des interactions effectuées sur le site afin de proposer une meilleure expérience dans le futur. Nous pouvons contracter les services de tiers afin de nous aider à mieux comprendre les visiteurs de notre site. Ces tiers ont l’autorisation d’utiliser ces données seulement à des fins d’améliorations.
-
-
Divulguons-nous des données à des tiers ?
-
-
Nous n’échangeons pas, ne vendons pas ni effectuons de quelconques transferts avec des tiers d’informations permettant de vous identifier personnellement. Cela n’inclut pas les tiers de confiance qui nous aident à gérer notre entreprise et à vous servir tant que ces tiers s’accordent à garder lesdites informations confidentielles. Nous pouvons être amenés à délivrer vos informations lorsque jugé adéquat afin de respecter la loi, d’appliquer la politique de notre site, ou afin de protéger nos droits, ceux des autres, notre propriété ou sécurité. Cependant, aucune information permettant l’identification de nos visiteur⋅euse⋅s ne sera divulguée à des fins publicitaires, commerciales ou tout autre usage.
-
-
Liens vers des tiers
-
-
Nous pouvons être amenés à inclure ou offrir les services ou produits de tiers sur notre site. Ces tiers possèdent leur propre politique de confidentialité. Nous ne sommes donc pas responsables du contenu ou activités desdits tiers. Néanmoins, nous cherchons à protéger l’intégrité de notre site et sommes ouverts à toute remarque concernant ces tiers.
-
-
Children's Online Privacy Protection Act
-
-
Notre site, nos produits et services sont tous destinés à l’usage de personnes âgées de 13 ans ou plus. Si ce serveur est hébergé aux États-Unis et que vous êtes âgé⋅e de moins de 13 ans, au vu du COPPA (Children's Online Privacy Protection Act) n’utilisez pas ce site.
-
-
Politique de confidentialité en ligne
-
-
Cette politique de confidentialité en ligne s'applique uniquement aux informations collectées par le biais de notre site et non aux informations collectées hors ligne.
-
-
Votre consentement
-
-
En utilisant notre site, vous consentez à la présente politique de confidentialité.
-
-
Changements de notre politique de confidentialité
-
-
Si nous décidons d’apporter des changements à notre politique de confidentialité, nous les publierons sur cette page.
-
-
Ce document est distribué sous licence CC-BY-SA. Il a été mis à jour pour la dernière fois le 31 mai 2013. Il a été traduit en français en juillet 2017.
-
-
Originellement adapté à partir de la politique de confidentialité de Discourse.
title: "%{instance} Conditions d’utilisations et politique de confidentialité"
themes:
default: Mastodon
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index bddc1b789..f4ca7e8c5 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -665,74 +665,6 @@ gl:
reblogged: promocionada
sensitive_content: Contido sensible
terms:
- body_html: |
-
Política de intimidade
-
-
Qué información recollemos?
-
-
Recollemos información sobre vostede cando se rexistra no noso sitio web e recollemos datos cando participa no foro lendo, escribindo e evaluando o contido compartido aquí.
-
-
Cando se rexistra no noso sitio, podería solicitarselle o seu nome e enderezo de correo electrónico. Vostede podería, porén, visitar o noso sitio sin rexistrarse. O seu enderezo de correo será verificado con un correo con unha ligazón única. Si esa ligazón é visitada, saberemos que vostede controla ese enderezo de correo.
-
-
Cando se rexistra e publica, almacenamos o enderezo IP desde onde publicou. Poderiamos tamén gardar rexistros do servidor que inclúan a IP de cada petición ao realizada ao servidor.
-
-
Con qué fin utilizamos a súa información?
-
-
Toda a información recollida de vostede podería ser utilizada dos seguintes xeitos:
-
-
-
Para individualizar a súa experiencia — a súa información axúdanos a respostar mellor as súas necesidades individuais.
-
Para mellorar o noso sitio —esforzámonos en mellorar o que ofrece o noso sitio baseándonos na información e críticas que vostede nos proporciona.
-
Para mellorar o servizo ao cliente —a súa información axúdanos a respostar máis eficientemente as súas peticións de servizo ao cliente e axuda.
-
Para enviar correos electrónicos periodicamente — O enderezo de correo que nos proporciona podería ser utilizado para enviarlle información, notificacións que solicitou sobre cambios ou asuntos ou en resposta ao ser nome de usuaria, responder a enquisas, e/ou outras peticións ou cuestións.
-
-
-
Cómo protexemos a súa información?
-
-
Implementamos varias medidas de seguridade para manter a seguiridade da súa información personal cando introduce, envía ou accede a súa información personal.
-
-
Qué é a política de retención dos seus datos?
-
-
Faremos un sincero esforzo para:
-
-
-
Manter rexistros do sistema con enderezos IP de todas as peticións feitas a este servidor no seu nome non máis de 90 días.
-
Manter os enderezos IP asociados a usuarias rexistradas e as súas mensaxes non máis de 5 anos.
-
-
-
Utilizamos cookies?
-
-
Si. As cookies son pequenos ficheiros que un sitio ou o seu proveedor de servizo transfire ao disco duro da súa computadora a través do navegador web (se vostede o permite). Estas cookies permiten ao sitio recoñer o seu navegador e, si ten unha conta rexistrada, asocialo coa súa conta.
-
-
Utilizamos cookies para comprender e gardar as súas preferencias para futuras visitas e compilar datos agregados sobre o tráfico do sitio e interacción co sitio de tal xeito que no futuro poidamos ofrecer unha mellor experiencia de uso do sitio e ferramentas. Poderiamos contratar servizos de terceiros para axudarnos a entender mellor as nosas visitantes. Estos proveedores de servizo non teñen permiso para utilizar a información recollida no noso nome excepto para axudarnos a xestionar e mellorar o noso negocio.
-
-
Mostramos información a terceiros alleos?
-
-
Non vendemos, nin negociamos con, ou transmitimos de outros xeitos a axentes terceiros alleos a información que a información que a identifica personalmente. Esto non inclúe terceiros de confianza que non axudan a operar o sitio, xestionar o negocio, ou servila, así estas partes se comprometan coa confidencialidade dos datos. Poderiamos revelar a súa información cando creamos que facelo así é axeitado para cumplir coa lei, cumplir coas normas do sitio ou protexer os nosos dereitos, propiedades ou seguridade e os de outras. Porén, non se proporcionará información identificable a terceiros para publicidade, márquetin ou outros usos.
-
-
Ligazóns a terceiros
-
-
De xeito ocasional, a nosa discreción, poderiamos incluír ofertas de productos e servizos de terceiros no noso sitio. Estos sitios de terceiros teñen políticas de intimidade propias. Polo tanto non temos responsabilidade ou obligacións polo contido e actividades de esos sitios. Con todo, procuramos protexer a integridade do noso sitio e agradecemos calquer opinión e crítica sobre estos sitios.
-
-
Cumplimento coa Children's Online Privacy Protection Act
-
-
O noso sitio, productos e servizos están dirixidos as personas con 13 anos como mínimo. Si este servidor está en USA e vostede ten menos de 13 anos, a requerimento da COPPA (Children's Online Privacy Protection Act) non utilice este sitio web.
-
-
Política de intimidade só en liña
-
-
Esta política de intimidade aplícase só a información recollida no noso sitio e non a información recollida fora de liña.
-
-
O seu consentimento
-
-
Utilizando o noso sitio, vostede acepta esta política de intimidade.
-
-
Cambios na política de intimidade
-
-
Si decidimos cambiar a nosa política de intimidade publicaremos esos cambios en esta páxina.
-
-
Este documento ten licenza CC-BY-SA. Foi actualizado o 31 de maio de 2013.
title: "%{instance} Termos do Servizo e Política de Intimidade"
themes:
default: Mastodon
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index 6be82c1de..2560b3816 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -633,76 +633,6 @@ hu:
reblogged: reblogolt
sensitive_content: Szenzitív tartalom
terms:
- body_html: |
-
Adatvédelmi és adatkezelési nyilatkozat
-
-
Milyen információt gyűjtünk?
-
-
Az oldalra történő regisztráció és a szolgáltatás használata - olvasás, tartalom létrehozása, tartalommegosztás - során információt gyűjtünk veled kapcsolatban.
-
-
A regisztráció során kérhetjük nevedet és e-mail címedet. Az oldalt természetesen regisztráció nélkül is felkeresheted. Az e-mail címed megerősítése egy egyedi információt tartalmazó link segítségével történik. Mondott linkre kattintva ellenőrizzük, hogy valóban te vagy a cím kezelője.
-
-
Regisztrált felhasználók esetében tülkök írásakor rögzítjük a felhasználó IP-címét. A szerver napjófájlja szintén tárolhatja ezt az IP-címet, valamint a szerverre érkező minden kérés küldő-oldali IP-címét.
-
-
Mire használjuk a begyűjtött információt?
-
-
Minden begyűjtött információt az alábbi okokból használhatunk fel:
-
-
-
A felhasználói élmény személyre szabásához — a tőled gyűjtött információ segítségével biztosíthatjuk számodra az egyedi igényeknek történő megfelelést.
-
Szolgáltatásunk fejlesztéséhez — folyamatosan igyekszünk fejlődni és jobbá válni, és ezt a tőled kapott adatok és visszajelzések is nagyban segítik.
-
Az ügyféltámogatás fejlesztéséhez — a gyűjtött adatok segítségével hatékonyabban támogathatjuk felhasználóinkat, ha azok segítségre szorulnak.
-
E-mail értesítések küldéséhez — a megadott e-mail címedre küldjük ki az általad igényelt értesítéseket, a szolgáltatásra vonatkozó információkat és a válaszokat a tőled beérkező megkeresésekre.
-
-
-
Hogyan védjük a tőled gyűjtött információt?
-
-
Bitonsági mechanizmusok egész sorát vetjük be annak érdekében, hogy biztosítsuk a tőled származó személyes és használatai adatok és információk biztonságát.
-
-
Meddig tároljuk a tőled származó adatokat?
-
-
Minden tőlünk telhetőt megteszünk annak érdekében, hogy
-
-
-
a szerver naplófájljaiban tárolt, a szerverre érkező kérések küldő-oldali IP-címét maximum 90 napig,
-
a regisztrált felhasználók tülkjeinek eredeti IP-címét pedig maximum 5 évig
-
-
-
tároljuk.
-
-
Használunk-e sütiket?
-
-
Igen. A sütik olyan kisméretű fájlok, amelyeket a szolgáltatások vagy internet-szolgáltatók küldenek a felhasználó számítógépére a böngészőn keresztül (természetesen csak abban az esetben, ha a felhasználó ezt engedélyezi). Oldalunk ezen sütik segítségével ismerik fel a böngésződet és - amennyiben rendelkezel nálunk fiókkal - kötik össze azt a felhasználói fiókoddal.
-
-
A sütik segítségével jobban megérthetjük használati szokásaidat, eltárolhatjuk beállításaidat következő látogatásodig, valamint így mérhetjük az oldal látogatottságát és használatát, mely adatok segítenek abban, hogy jobbá tehessük az általunk nyújtott szolgáltatást. Esetenként harmadik féllel is kapcsolatba léphetünk a kinyert használati adatok jobb megértése érdekében. Ezen harmadik felek számára azonban az adatok használata szigorú feltételekhez kötött: kizárólag az engedélyünkkel és királólag a mi szolgáltatásunk fejlesztésével összefüggésben használhatják azokat.
-
-
Milyen információt adunk ki külső szereplőknek?
-
-
Soha, semmilyen körülmények között nem adunk ki, át vagy el külső szereplőknek olyan adatot, amelynek segítségével egyes felhasználóink egyedileg azonosíthatók. Ez nem vonatkozik olyan harmadik felekre, melyek jelen szolgáltatás üzemeltetésében, javításában vagy támogatásában segítségünkre vannak – ezeket a feleket azonban titoktartási szerződés köti mondott adatokkal kapcsolatban. A gyűjtött adatokat ezen felül megfelelő meghagyás megléte esetén kiadhatjuk a törvény és a rendfenntartás képviselőinek, amennyiben ezen adatoknak jog-, élet- vagy vagyonvédelmi jelentőségük van. Hirdetési- és marketing-, valamint egyéb, a fentiekben nem érintett célból csak olyan adatok adhatók ki, amelyek nem teszik lehetővé az egyes felhasználók egyedi azonosítását.
-
-
Harmadik felekre mutató hivatkozások
-
-
Esetenként elhelyezhetünk harmadik fél által ajánlott termékekre vagy szolgáltatásokra mutató hivatkozásokat az oldalon. Ezen harmadik feleknek saját, tőlünk független adatvédelmi és adatkezelési nyilatkozatuk van. Ennek értelmében az oldal üzemeltetői semmilyen felelősséget nem tudnak vállalni az ezen harmadik fél által üzemeltetett oldalak viselkedésével és tartalmával kapcsolatban. Ugyanakkor arra törekszünk, hogy mindenben saját felhasználóink érdekeit képviseljük, így minden, a fenti harmadik felekkel kacsolatos visszejelzést szívesen veszünk.
-
-
Megfelelés a Gyermekek Online Adatvédelméről Szóló Rendeletnek
-
-
Az oldal, valamint az azon keresztül nyújtott szolgáltatás a 13 éven felülieket célozza. Amennyiben ez a szerver az Amerikai Egyesült Államok területén található és te nem vagy még 13 éves, a COPPA (Gyermekek Online Adatvédelméről Szóló Rendelet) értelmében kérjük ne használd ezt az oldalt és szolgáltatást.
-
-
Az adatvédelmi és adatkezelési nyilatkozat hatálya
-
-
Jelen adatvédelmi és adatkezelési nyilatkozat kizárólag az oldalunkon keresztül gyűjtött online adatokra vonatkozik, offline módon gyűjtött adatokra nem terjed ki.
-
-
Használói beleegyezés
-
-
Az oldal és a szolgáltatás használatával elfogadottnak tekinted jelen adatvédelmi és adatkezelési nyilatkozatot.
-
-
A nyilatkozat módosításairól
-
-
Amennyiben a jövőben módosítjuk jelen adatvédelmi és adatkezelési nyilatkozatunkat, a módosított szöveg ugyanezen oldalon lesz megtalálható.
-
-
Jelen dokumentum a CC-BY-SA licenc alatt érhető el. Angol eredetijének utolsó módosítása: 2013. május 31.
우리는 귀하가 우리 사이트에 가입할 때, 그리고 우리의 포럼에 읽고, 쓸 때, 그리고 포럼에 게시된 공유된 콘텐츠를 평가할 때 정보를 수집합니다.
-
-
우리 사이트에 가입할 때, 귀하는 이름과 이메일 주소 입력을 요구 받을 수 있습니다. 하지만 귀하는 우리의 사이트를 가입하지 않고도 방문할 수 있습니다. 귀하의 이메일 주소는 고유한 링크를 담고 있는 이메일로 검증 될 것입니다. 만약 귀하가 그 링크를 방문한다면, 우리는 귀하가 그 이메일 주소를 소유하고 있다는 것을 알 수 있습니다.
-
-
가입을 하고 글을 쓸 때, 우리는 글이 어떤 IP에서 작성 되었는지 기록합니다. 또한 우리는 모든 요청에 대한 IP 주소를 담고 있는 서버 로그를 보관할 수 있습니다.
-
-
우리가 귀하의 정보를 어떻게 사용하나요?
-
-
우리가 귀하에게서 수집하는 어떠한 정보는 다음 중 하나와 같은 방법으로 사용될 수 있습니다:
-
-
-
귀하의 경험을 개인화 하기 위해 — 귀하의 정보는 우리가 귀하의 개별적인 요구에 더 나은 응답을 할 수 있도록 돕습니다.
-
우리의 사이트를 개선하기 위해 — 우리는 귀하에게 받는 정보와 귀하에게 받는 피드박을 바탕으로 우리의 사이트 내용을 계속 개선하기 위해 노력합니다.
-
고객 서비스를 개선하기 위해 — 귀하의 정보는 우리가 귀하의 서비스 요청과 지원 요청에 더 효과적으로 응답할 수 있게 돕습니다.
-
주기적인 이메일을 보내기 위해 — 귀하가 제공하는 이메일 주소는 귀하에게 정보, 귀하가 요청하는 주제에 대한 변경과 귀하의 유저 이름에 대한 응답에 대한 알림, 문의에 대한 답, 또는 다른 요청과 질문을 보내는 데에 사용될 수 있습니다.
-
-
-
우리가 어떻게 귀하의 정보를 보호하나요?
-
-
우리는 귀하가 개인정보를 입력, 제출, 접근 할 때 귀하의 개인정보의 안전을 유지하기 위한 여러가지 보안 방법을 구현합니다.
-
-
정보 보관 정책은 어떻게 되나요?
-
-
우리는 다음과 같이 노력 하겠습니다:
-
-
-
모든 요청에 대한 IP 주소를 담고 있는 서버 로그를 최대 90일까지 보관합니다.
-
등록된 사용자와 관련된 IP 주소와 그들의 게시물들을 최대 5년까지 보관합니다.
-
-
-
쿠키를 사용하나요?
-
-
네. 쿠키는 사이트나 서비스 제공자가 (만약 허용하신다면) 웹 브라우저를 통해 귀하의 컴퓨터 하드디스크에 전송하는 작은 파일들입니다. 이 쿠키들은 사이트가 귀하의 브라우저를 인식하게 하고, 만약 가입한 계정이 있다면 브라우저를 가입한 계정과 연관짓는 일을 가능하게 합니다.
-
-
우리는 쿠키를 사용해 귀하의 환경설정을 미래의 방문을 위해 저장하고, 사이트 접근 기록과 사이트 상호작용 기록을 모아 미래에 우리가 더 나은 사이트 경험과 도구를 제공할 수 있도록 합니다. 우리는 제 3자의 서비스 제공자와 계약하여 우리 사이트의 방문자에 대해 더 나은 이해를 하기 위해 도움을 받을 수 있습니다. 이러한 서비스 제공자들은 우리가 더 나은 서비스를 제공하도록 돕는 목적 외에는 이 정보를 사용할 수 없습니다.
-
-
우리가 외부에 정보를 공개하나요?
-
-
우리는 귀하를 식별할 수 있는 정보를 외부에 팔거나, 거래하거나, 전송하지 않습니다. 이는 우리가 우리의 사이트를 운영하고, 사업을 하고, 귀하에게 서비스를 제공하는 데에 도움을 주는 믿을 수 있는 제 3자의 서비스 제공자를 포함하지 않으며, 이는 그 서비스 제공자가 이 정보를 비밀로 취급하는 것에 동의하는지에 따라 다릅니다. 우리는 또한 법을 지키는 것, 우리 사이트의 정책을 집행하는 것, 우리와 다른 사람들의 권리, 재산, 안전을 보호하는 것으로 인해 정보 공개가 적합하다고 생각되면 정보를 공개 할 수 있습니다. 그러나, 귀하를 식별할 수 없는 방문자 정보는 외부에 마케팅, 광고, 혹은 다른 용도로 제공될 수 있습니다.
-
-
제 3자 링크
-
-
종종, 우리의 재량에 따라 우리의 사이트에 제 3자의 상품이나 서비스를 포함하거나 제공할 수 있습니다. 이러한 제 3자 사이트는 독립적인 개인정보 정책을 가지고 있습니다. 이러한 링크된 제 3자 사이트의 내용과 활동에 대해서 우리는 어떠한 의무와 법적 책임을 가지고 있지 않습니다. 그래도 우리는 그 사이트에 대한 피드백을 환영하며, 우리 사이트만의 정체성을 유지하도록 노력하겠습니다.
We collect information from you when you register on our site and gather data when you participate in the forum by reading, writing, and evaluating the content shared here.
-
-
When registering on our site, you may be asked to enter your name and e-mail address. You may, however, visit our site without registering. Your e-mail address will be verified by an email containing a unique link. If that link is visited, we know that you control the e-mail address.
-
-
When registered and posting, we record the IP address that the post originated from. We also may retain server logs which include the IP address of every request to our server.
-
-
What do we use your information for?
-
-
Any of the information we collect from you may be used in one of the following ways:
-
-
-
To personalize your experience — your information helps us to better respond to your individual needs.
-
To improve our site — we continually strive to improve our site offerings based on the information and feedback we receive from you.
-
To improve customer service — your information helps us to more effectively respond to your customer service requests and support needs.
-
To send periodic emails — The email address you provide may be used to send you information, notifications that you request about changes to topics or in response to your user name, respond to inquiries, and/or other requests or questions.
-
-
-
How do we protect your information?
-
-
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information.
-
-
What is your data retention policy?
-
-
We will make a good faith effort to:
-
-
-
Retain server logs containing the IP address of all requests to this server no more than 90 days.
-
Retain the IP addresses associated with registered users and their posts no more than 5 years.
-
-
-
Do we use cookies?
-
-
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
-
-
We use cookies to understand and save your preferences for future visits and compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future. We may contract with third-party service providers to assist us in better understanding our site visitors. These service providers are not permitted to use the information collected on our behalf except to help us conduct and improve our business.
-
-
Do we disclose any information to outside parties?
-
-
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety. However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
-
-
Third party links
-
-
Occasionally, at our discretion, we may include or offer third party products or services on our site. These third party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
Our site, products and services are all directed to people who are at least 13 years old. If this server is in the USA, and you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
-
-
Online Privacy Policy Only
-
-
This online privacy policy applies only to information collected through our site and not to information collected offline.
-
-
Your Consent
-
-
By using our site, you consent to our web site privacy policy.
-
-
Changes to our Privacy Policy
-
-
If we decide to change our privacy policy, we will post those changes on this page.
-
-
This document is CC-BY-SA. It was last updated May 31, 2013.
title: "%{instance} Terms of Service and Privacy Policy"
themes:
default: Mastodon
diff --git a/config/locales/no.yml b/config/locales/no.yml
index 3adf71bee..d5edb3975 100644
--- a/config/locales/no.yml
+++ b/config/locales/no.yml
@@ -633,74 +633,6 @@
reblogged: fremhevde
sensitive_content: Følsomt innhold
terms:
- body_html: |
-
Personvernserklæring
-
-
Hvilke opplysninger samler vi?
-
-
Vi samler opplysninger fra deg når du registrerer deg på nettstedet vårt, og vi samler data når du deltar på forumet ved å lese, skrive og evaluere innholdet som deles her.
-
-
Når du registrerer deg på nettstedet vårt, kan du bli bedt om å oppgi navnet og e-postadressen din. Imidlertid kan du besøke nettstedet vårt uten å registrere deg. E-postadressen din vil bli bekreftet med en e-post som inneholder en unik lenke. Hvis siden den lenker til, blir besøkt, vet vi at du har kontroll over e-postadressen.
-
-
Når du registrerer deg og skriver innlegg, registrerer vi IP-adressen som innlegget stammer fra. Vi kan også oppbevare logger som inkluderer IP-adressen til alle forespørslene sendt til tjeneren vår.
-
-
Hva bruker vi opplysningene dine til?
-
-
Alle opplysningene vi samler fra deg, kan bli brukt på en av følgende måter:
-
-
-
For å gjøre opplevelsen din mer personlig. Opplysningene dine hjelper oss å svare bedre på dine individuelle behov.
-
For å forbedre nettstedet vårt. Vi jobber konstant for å forbedre nettstedets tilbud basert på opplysningene og tilbakemeldingene vi mottar fra deg.
-
For å forbedre vår kundeservice. Dine opplysninger hjelper oss å svare mer effektivt på dine forespørsler sendt til kundeservice eller behov om støtte.
-
For å sende periodiske e-poster. E-postadressen du oppgir, kan bli brukt til å sende deg informasjon, påminnelser som du ber om ved endringer av emner eller ved svar til brukernavnet ditt, til henvendelser, og/eller andre forspørsler eller andre spørsmål.
-
-
-
Hvordan sikrer vi opplysningene?
-
-
Vi gjennomfører flere sikkerhetstiltak for å holde personopplysningene dine sikre når du skriver inn, lagrer eller henter dem.
-
-
Hva er retningslinjene deres for lagring av data?
-
-
Vi vil forsøke i god tro å:
-
-
-
Ikke oppbevare tjener-logger som inneholder IP-adressen til alle forespørslene til denne tjeneren i lenger enn i 90 dager.
-
Ikke oppbevare IP-adressene forbundet med registrerte brukere og deres innlegg lenger enn i 5 år.
-
-
-
Bruker vi informasjonskapsler?
-
-
Ja. Informasjonskapsler er små filer som et nettsted eller dets tjenesteleverandør overfører til harddisken på datamaskinen din gjennom nettleseren din (dersom du tillater det). Disse informasjonskapslene gjør det mulig for nettstedet å gjenkjenne nettleseren din og, dersom du har en konto, knytte nettleseren til den.
-
-
Vi bruker informasjonskapsler for å forstå og lagre preferansene dine for fremtidige besøk og for å samle aggregatdata om trafikk på og samhandling med nettstedet slik at vi kan tilby bedre opplevelser og verktøy på nettstedet i fremtiden. Vi kan inngå avtaler med tredjeparts tjenesteleverandører for å bistå oss i å forstå besøkerne våres bedre. Disse tjenesteleverandørene har ikke lov til å bruke opplysningene samlet på våres vegne unntatt til å hjelpe oss å gjennomføre og forbedre anliggendet vårt.
-
-
Gir vi noen opplysninger videre til andre parter?
-
-
Vi verken selger, handler med eller overfører på noen annen måte til andre parter dine identifiserbare personopplysninger. Dette inkluderer ikke tredjeparter som har vår tillit og bistår oss i å drive nettstedet, utføre våre anliggender eller yter tjenester til deg, så lenge disse partene samtykker til å behandle disse opplysningene fortrolig. Vi kan også frigi opplysningene dine dersom vi tror at å frigi dem er hensiktsmessig for å overholde loven, håndheve nettstedet retningslinjer eller beskytte våre og andres rettigheter. Imidlertid kan opplysninger som ikke er personlig identifiserbare, bli delt med andre parter for markedsføring, reklame eller annet bruk.
-
-
Tredjeparts lenker
-
-
Av og til, etter skjønn, kan vil inkludere eller tilby tredjeparts produkter eller tjenester på nettstedet vårt. Disse tredjeparts nettstedene har separate og selvstendige personvernerklæringer. Vi bærer derfor intet ansvar eller forpliktelser for innholdet eller aktivitetene til disse nettstedene det lenkes til. Ikke mindre prøver vi å bevare vår eget nettsteds integritet og ønsker enhver tilbakemelding om disse nettstedene velkomne.
-
-
Overensstemmelse med Children's Online Privacy Protection Act
-
-
Nettstedet er rettet mot folk som er minst 13 år gamle. Dersom denne tjeneren er i USA, og du er under 13 år i henhold til kravene i COPPA (Children's Online Privacy Protection Act), ikke bruk dette nettstedet.
-
-
Personvernerklæring bare for nettet
-
-
Denne nett-personvernerklæringen gjelder bare for informasjon samlet gjennom nettstedet vårt og ikke for opplysninger samlet når en er frakoblet.
-
-
Ditt samtykke
-
-
Ved å bruke dette nettstedet samtykker du til nettstedets personvernerklæring.
-
-
Endringer i vår personvernerklæring
-
-
Dersom vi beslutter å endre personvernerklæringen vår, vil vi publisere disse endringene på denne siden.
-
-
Dette dokumentet er lisensiert under CC-BY-SA. De ble sist oppdatert 12. april 2017.
title: "%{instance} Personvern og villkår for bruk av nettstedet"
themes:
default: Mastodon
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 49b1df8bf..f8e819c53 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -742,74 +742,6 @@ oc:
reblogged: a partejat
sensitive_content: Contengut sensible
terms:
- body_html: |
-
Politica de confidencialitat
-
-
Quinas informacions reculhèm ?
-
-
Collectem informacions sus vos quand vos marcatz sus nòstre site e juntem las donadas quand participatz a nòstre forum en legir, escriure e notar lo contengut partejat aquí.
-
-
Pendent l’inscripcion podèm vos demandar vòstre nom e adreça de corrièl. Podètz çaquelà visitar nòstre site sens vos marcar. Verificarem vòstra adreça amb un messatge donant un ligam unic. Se clicatz sul ligam sauprem qu’avètz lo contraròtle de l’adreça.
-
-
Quand sètz marcat e que publicatz quicòm, enregistrem l’adreça IP d’origina. Podèm tanben salvagardar los jornals del servidor que tenon l’adreça IP de totas las demandas fachas al nòstre servidor.
-
-
Qué fasèm de vòstras informacions ?
-
-
Totas las informacions que collectem de vos pòdon servir dins los cases seguents :
-
-
-
Per personalizar vòstre experiéncia — vòstras informacions nos ajudaràn a respondre melhor a vòstres besonhs individuals.
-
Per melhorar nòstre site — s’eforcem de longa a melhorar çò que nòstre site ofrís segon las informacions e los comentaris que recebèm de vòstra part.
-
Per melhorar nòstre servici client — vòstras informacions nos ajudan per respondre amb mai eficacitat a vòstras demandas d’assisténcia.
-
Per enviar periodicament de corrièls — Podèm utilizar l’adreça qu’avètz donada per vos enviar d’informacions e de notificacions que demandatz tocant de cambiaments dins los subjèctes del forum o en responsa a vòstre nom d’utilizaire, en responsa a una demanda, e/o tota autra question.
-
-
-
Cossí protegèm vòstras informacions ?
-
-
Apliquem tota una mena de mesuras de seguretat per manténer la fisança de vòstras informacions personalas quand las picatz, mandatz, o i accedètz.
-
-
Quala es vòstra politica de conservacion de donadas ?
-
-
Farem esfòrces per :
-
-
-
Gardar los jornals del servidor que contenon las adreças IP de totas las demandas al servidor pas mai de 90 jorns.
-
Gardar las adreças IP ligadas als utilizaires e lors publicacions pas mai de 5 ans.
-
-
-
Empleguem de cookies ?
-
-
Òc-ben. Los cookies son de pichons fichièrs qu’un site o sos provesidors de servicis plaçan dins lo disc dur de vòstre ordenador via lo navigator Web (Se los acceptatz). Aqueles cookies permeton al site de reconéisser vòstre navigator e se tenètz un compte enregistrat de l’associar a vòstre compte.
-
-
Empleguem de cookies per comprendre e enregistrar vòstras preferéncias per vòstras visitas venentas, per recampar de donadas sul trafic del site e las interaccions per dire que posquem ofrir una melhora experiéncia del site e de las aisinas pel futur. Pòt arribar que contractèssem amb de provesidors de servicis tèrces per nos ajudar a comprendre melhor nòstres visitors. Aqueles provesidors an pas lo drech que d’utilizar las donadas collectadas per nos ajudar a menar e melhorar nòstre afar.
-
-
Divulguem d’informacions a de tèrces ?
-
-
Vendèm pas, comercem o qualque transferiment que siasque a de tèrces vòstras informacions personalas identificablas. Aquò inclutz pas los tèrces partits de confisança que nos assiston a menar nòstre site, menar nòstre afar o vos servir, baste que son d’acòrd per gardar aquelas informacions confidencialas. Pòt tanben arribar que liberèssem vòstras informacions quand cresèm qu’es apropriat d’o far per se sometre a la lei, per refortir nòstras politicas, o per protegir los dreches, proprietats o seguritat de qualqu’un o de nosautres. Pasmens es possible que mandèssem d’informacions non-personalas e identificablas de nòstres visitors a d’autres partits per d’utilizacion en marketing, publicitat o un emplec mai.
-
-
Ligams de tèrces
-
-
Pòt arribar, a nòstra discrecion, qu’incluguèssem o ofriguèssem de produches o servicis de tèrces partits sus nòstre site. Aqueles sites tèrces an de politicas de confidencialitats separadas e independentas. En consequéncia avèm pas cap de responsabilitat pel contengut e las activitats d’aqueles sites ligats. Pasmens cerquem de protegir l’integritat de nòstre site e aculhèm los comentaris tocant aqueles sites.
-
-
Conformitat amb la lei de proteccion de la confidencialitat dels mainatges
-
-
Nòstre site, nòstres produches e servicis son totes destinats a de monde d’almens 13 ans. S’aqueste servidor se tròba en los Estats Units per acontentar las exigéncias del COPPA (Children's Online Privacy Protection Act) utilizetz pas aqueste site.
-
-
Politica de confidencialitat en linha solament
-
-
Aquesta politica de confidencialitat s’aplica pas qu’a las informacions collectadas via nòstre site e non pas a las informacions collectadas fòra linha.
-
-
Vòstre consentiment
-
-
N’utilizant nòstre site, consentètz a nòstra politica de confidencialitat.
-
-
Cambiament dins nòstra politica de confidencialitat
-
-
Se decidèm de cambiar nòstra politica de confidencialitat, publicarem los cambiaments sus aquesta pagina.
-
-
Aqueste document es jos licéncia CC-BY-SA. Darrièra mesa a jorn lo 31 de mai de 2013
title: Condicions d’utilizacion e politica de confidencialitat de %{instance}
time:
formats:
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index c62636081..64c1ff5ea 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -700,74 +700,6 @@ pl:
reblogged: podbił
sensitive_content: Wrażliwa zawartość
terms:
- body_html: |
-
Polityka prywatności
-
-
Jakie informacje zbieramy?
-
-
Zbieramy informacje podane przy rejestracji i treści utworzone w trakcie korzystania z serwisu.
-
-
Podczas rejestracji, możesz otrzymać prośbę o podanie adresu e-mail. Możesz jednak odwiedzać stronę bez rejestracji. Adres zostanie zweryfikowany przez kliknięcie w link wysłany w wiadomości. Dzięki temu wiemy, że jesteś właścicielem tego adresu.
-
-
Podczas rejestracji i tworzenia wpisów, Twój adres IP jest zapisywany na naszych serwerach. Możemy też przechowywać adres IP użyty przy każdej operacji w serwisie.
-
-
Jak wykorzystujemy zebrane informacje?
-
-
Zebrane informacje mogą zostać w jednym z następujących celach:
-
-
-
Aby poprawić wrażenia — informacje o Tobie pomagają w dostosowywaniu serwisu do Twoich potrzeb.
-
Aby usprawnić stronę — nieustannie staramy się ulepszyć stronę na podstawie informacji o Tobie i Twoich opinii.
-
Aby usprawnić obsługę klienta — informacje pomogą obsłudze klienta utrzymywać kontakt z Tobą.
-
Aby okazjonalnie wysyłać wiadomości e-mail — Na podany adres e-mail mogą zostać wysłane wiadomości o wspomnieniu o Tobie we wpisach, przejrzeniu Twojego zgłoszenia i innych interakcji z Tobą.
-
-
-
Jak zabezpieczamy dane?
-
-
Korzystamy z wielu zabezpieczeń, aby utrudnić osobom niepowołanym dostęp do danych, które wprowadzasz, publikujesz i czytasz.
-
-
Jak długo przechowujecie dane?
-
-
Dołożymy wszelkich starań, aby przechowywać:
-
-
-
dzienniki serwera zawierające adresy IP przypisane do każdych operacji nie dłużej niż 90 dni.
-
adresy IP przypisane do użytkowników i ich wpisów nie dłużej niż 5 lat.
-
-
-
Czy używamy plików cookies?
-
-
Tak. Pliki cookies (zwane często ciasteczkami) są małymi zbiorami danych przechowywanych na Twoim dysku przez stronę internetową, aby rozpoznawać przeglądarkę i powiązać ją (jeżeli jesteś zarejestrowany/a) z Twoim kontem, jeżeli na to pozwolisz.
-
-
Możemy używać ciasteczek, aby skonfigurować stronę na podstawie zapisanych preferencji, oraz dostosować ją do potrzeb innych użytkowników. Możemy korzystać z usług firm trzecich pomagających w zrozumieniu potrzeb użytkownika. Te usługi nie mogą korzystać ze zdobytych danych w celach innych niż analiza pomagająca ulepszać ten serwis.
-
-
Czy przekazujecie dane podmiotów trzecim?
-
-
Nie dokonujemy transakcji danych pozwalających na identyfikację Twojej osoby umieszczonych na tym serwisie. Nie oznacza to, że nie przekazujemy ich zaufanym podmiotom, które korzystają z nich poufnie. Możemy jednak udostępniać dane, jeżeli jest to wymagane prawnie, lub dla utrzymania bezpieczeństwa strony i innych użytkowników. W celach marketingowych (i podobnych) mogą zostać użyte jedynie dane niepozwalające na identyfikację osoby.
-
-
Odnośniki do treści stron trzecich
-
-
Czasem na stronie mogą pojawić się odnośniki do stron trzecich. Mają one odrębne regulaminy i politykę prywatności. Nie odpowiadamy więc za zawartość tych stron. Dokładamy jednak wszelkich starań, aby nie stanowiły one zagrożenia, prosimy jednak o opinie na temat ich wykorzystania.
Ta strona i usługa jest przeznaczona dla osób, które ukończyły 13 lat. Jeżeli serwer znajduje się na terenie USA i nie masz ukończonych 13 lat, zgodnie z amerykańską ustawą COPPA (Children's Online Privacy Protection Act) nie możesz korzystać z tego serwisu.
-
-
Polityka prywatności dotyczy tylko Internetu
-
-
Ta polityka prywatności dotyczy jedynie danych zbieranych w Internecie, nie tych, które przechowywane są na Twoim komputerze, np. pliki cookies.
-
-
Wyrażenie zgody
-
-
Korzystanie ze strony jest równoznaczne z akceptacją naszej polityki prywatności.
-
-
Zmiany w naszej polityce prywatności
-
-
Jeżeli zdecydujemy się na zmiany w polityce prywatności, zmiany pojawią się na tej stronie.
-
-
Dokument jest dostępny na licencji CC-BY-SA. Ostatnio modyfikowany 31 maja 2013, przetłumaczony 4 lipca 2017. Tłumaczenie (mimo dołożenia wszelkich starań) może nie być w pełni poprawne.
Coletamos informações quando você se cadastra em nosso site e capturamos dados quando você participa do fórum lendo, escrevendo e analisando o conteúdo aqui compartilhado.
-
-
Quando você se registrar em nosso site, será requisitado que você ceda seu nome e endereço de e-mail. Você pode, porém, visitar nosso site sem se cadastrar. Seu endereço de e-mail será verificado por uma mensagem contendo um link único. Se este link for visitado, saberemos que você controla este endereço de e-mail.
-
-
Quando registrado e postando, nós gravamos o endereço de IP de onde a postagem se originou. Nós também podemos reter logs de serviores que incluem o endereço de IP em cada requisição para o nosso servidor.
-
-
Para que usamos essas informações?
-
-
Quaisquer das informações que coletamos podem ser usadas das seguintes formas:
-
-
-
Para personalizar a sua experiência — suas informações nos ajudam a nos adequar melhor às suas necessidades individuais.
-
Para melhorar nosso site — nós continuamente nos esforçamos para aprimorar nosso site baseados na informação e no feedback que recebemos de você.
-
Para aprimorar o serviço ao consumidor — suas informações nos ajudam a responder efetivamente às suas requisições e solicitações por suporte.
-
Para mandar e-mails periódicos — O endereço de e-mail que você forneceu pode ser usado para lhe enviar informações, notificações que você requisitar sobre mudanças a determinados tópicos ou menções ao seu nome de usuário, responder requisições e/ou solicitações e perguntas.
-
-
-
Como protegemos as suas informações?
-
-
Nós implementamos uma variedade de medidas de segurança para manter a segurança de suas informações pessoais quando você insere, submete ou acessa as suas informações pessoais.
-
-
Qual a sua política de retenção de dados?
-
-
Faremos esforços de boa fé para:
-
-
-
Reter logs de servidor contendo o endereço IP de todas as requisições a este servidor por não mais que 90 dias.
-
Reter os endereços IP associados a usuários cadastrados e suas postagens por não mais que 5 anos.
-
-
-
Nós usamos cookies?
-
-
Sim. Cookies são pequenos arquivos que um site ou o provedor de serviço transfere para o armazenamento interno de seu computador através de seu navegador (se você permitir). Estes cookies habilitam o site para reconhecer o seu navegador e, se você ter um cadastro, associá-lo a esta conta.
-
-
Nós usamos cookies para entender e salvar as suas preferências para futuras visitas e compilar dados agregados sobre o tráfego do site para que possamos oferecer melhores experiências e ferramentas no futuro. Nós podemos contratar serviços de terceiros para nos auxiliar a entender melhor nossos visitantes. Estes provedores de serviço não são autoriza usar as informações coletadas em nosso nome exceto para nos ajudar a conduzir e aprimorar nosso funcionamento.
-
-
Nós revelamos informações para terceiros?
-
-
Nós não vendemos, tocamos ou transferimos para terceiros informações pessoais que te identificam. Isso não inclui partes em que confiamos para nos ajudar a operar nosso site, conduzir nosso funcionamento ou servir você desde que estes terceiros concordem em manter essas informações em segredo. Nós também podemos prover as suas informações para obedecer ordens judiciais, reforçar nossas políticas ou proteger nossos direitos ou de outrem, propriedades ou segurança. Entretanto, informações pessoais não identificáveis podem ser enviadas para outras partes para marketing, propaganda e outros usos.
-
-
Links de terceiros
-
-
Ocasionalmente, à nossa discrição, podemos icluir ou oferecer produtos ou serviços de terceiros em nosso site. Estes terceiros têm políticas de privacidade separadas e independentes. Nós, portanto, não nos responsabilizamos pelo conteúdo e atividades destes sites de terceiros. Occasionally, at our discretion, we may include or offer third party products or services on our site. Não obstante, nós procuramos proteger a integridade de nosso site e todo feedback sobre estes sites de terceiros é bem-vindo.
-
-
Obediência ao Ato de Proteção da Privacidade Online de Crianças
-
-
Nosso site, produtos e serviços são todos direcionados a pessoas que têm pelo menos 13 anos de idade. Se este servidor estiver nos EUA, e você tiver menos de 13 anos, pelos requerimentos da COPPA (Children's Online Privacy Protection Act) não use este site.
-
-
Política de Apenas Privacidade Online
-
-
Esta política de privacidade online se aplica somente a informações coletadas por nosso site e não a informações coletadas offline.
-
-
Seu Consentimento
-
-
Usando o nosso site, você concorda com a nossa política de privacidade.
-
-
Mudanças em nossa Política de Privacidade
-
-
Se decidirmos mudar a nossa política de privacidade, publicaremos as mudanças nesta página.
-
-
Este documento é CC-BY-SA. A sua última atualização aconteceu em 31 de maio de 2013.
title: "%{instance} Termos de Serviço e Política de Privacidade"
themes:
default: Mastodon
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index 5012e176f..27d4e88e3 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -635,74 +635,6 @@ pt:
reblogged: boosted
sensitive_content: Conteúdo sensível
terms:
- body_html: |
-
Política de privacidade
-
-
Quais são as informações que recolhemos?
-
-
Recolhemos informações quando te registas no nosso site e capturamos dados quando participas do fórum lendo, escrevendo e analisando o conteúdo aqui partilhado.
-
-
Quando te registas no nosso site, será requisitado que você ceda seu nome e endereço de e-mail. Você pode, porém, visitar nosso site sem se cadastrar. Seu endereço de e-mail será verificado por uma mensagem contendo um link único. Se este link for visitado, saberemos que você controla este endereço de e-mail.
-
-
Quando registrado e postando, nós gravamos o endereço de IP de onde a postagem se originou. Nós também podemos reter logs de serviores que incluem o endereço de IP em cada requisição para o nosso servidor.
-
-
Para que usamos essas informações?
-
-
Quaisquer das informações que coletamos podem ser usadas das seguintes formas:
-
-
-
Para personalizar a sua experiência — suas informações nos ajudam a nos adequar melhor às suas necessidades individuais.
-
Para melhorar nosso site — nós continuamente nos esforçamos para aprimorar nosso site baseados na informação e no feedback que recebemos de você.
-
Para aprimorar o serviço ao consumidor — suas informações nos ajudam a responder efetivamente às suas requisições e solicitações por suporte.
-
Para mandar e-mails periódicos — O endereço de e-mail que você forneceu pode ser usado para lhe enviar informações, notificações que você requisitar sobre mudanças a determinados tópicos ou menções ao seu nome de usuário, responder requisições e/ou solicitações e perguntas.
-
-
-
Como protegemos as suas informações?
-
-
Nós implementamos uma variedade de medidas de segurança para manter a segurança de suas informações pessoais quando você insere, submete ou acessa as suas informações pessoais.
-
-
Qual a sua política de retenção de dados?
-
-
Faremos esforços de boa fé para:
-
-
-
Reter logs de servidor contendo o endereço IP de todas as requisições a este servidor por não mais que 90 dias.
-
Reter os endereços IP associados a usuários cadastrados e suas postagens por não mais que 5 anos.
-
-
-
Nós usamos cookies?
-
-
Sim. Cookies são pequenos arquivos que um site ou o provedor de serviço transfere para o armazenamento interno de seu computador através de seu navegador (se você permitir). Estes cookies habilitam o site para reconhecer o seu navegador e, se você ter um cadastro, associá-lo a esta conta.
-
-
Nós usamos cookies para entender e salvar as suas preferências para futuras visitas e compilar dados agregados sobre o tráfego do site para que possamos oferecer melhores experiências e ferramentas no futuro. Nós podemos contratar serviços de terceiros para nos auxiliar a entender melhor nossos visitantes. Estes provedores de serviço não são autoriza usar as informações coletadas em nosso nome exceto para nos ajudar a conduzir e aprimorar nosso funcionamento.
-
-
Nós revelamos informações para terceiros?
-
-
Nós não vendemos, tocamos ou transferimos para terceiros informações pessoais que te identificam. Isso não inclui partes em que confiamos para nos ajudar a operar nosso site, conduzir nosso funcionamento ou servir você desde que estes terceiros concordem em manter essas informações em segredo. Nós também podemos prover as suas informações para obedecer ordens judiciais, reforçar nossas políticas ou proteger nossos direitos ou de outrem, propriedades ou segurança. Entretanto, informações pessoais não identificáveis podem ser enviadas para outras partes para marketing, propaganda e outros usos.
-
-
Links de terceiros
-
-
Ocasionalmente, à nossa discrição, podemos icluir ou oferecer produtos ou serviços de terceiros em nosso site. Estes terceiros têm políticas de privacidade separadas e independentes. Nós, portanto, não nos responsabilizamos pelo conteúdo e atividades destes sites de terceiros. Occasionally, at our discretion, we may include or offer third party products or services on our site. Não obstante, nós procuramos proteger a integridade de nosso site e todo feedback sobre estes sites de terceiros é bem-vindo.
-
-
Obediência ao Ato de Proteção da Privacidade Online de Crianças
-
-
Nosso site, produtos e serviços são todos direcionados a pessoas que têm pelo menos 13 anos de idade. Se este servidor estiver nos EUA, e você tiver menos de 13 anos, pelos requerimentos da COPPA (Children's Online Privacy Protection Act) não use este site.
-
-
Política de Apenas Privacidade Online
-
-
Esta política de privacidade online se aplica somente a informações coletadas por nosso site e não a informações coletadas offline.
-
-
Seu Consentimento
-
-
Usando o nosso site, você concorda com a nossa política de privacidade.
-
-
Mudanças em nossa Política de Privacidade
-
-
Se decidirmos mudar a nossa política de privacidade, publicaremos as mudanças nesta página.
-
-
Este documento é CC-BY-SA. A sua última atualização aconteceu em 31 de maio de 2013.
title: "%{instance} Termos de Serviço e Política de Privacidade"
themes:
default: Mastodon
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 108ca33e9..176ace92d 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -679,45 +679,6 @@ ru:
reblogged: продвинул(а)
sensitive_content: Чувствительный контент
terms:
- body_html: |
-
Privacy Policy
-
What information do we collect?
-
We collect information from you when you register on our site and gather data when you participate in the forum by reading, writing, and evaluating the content shared here.
-
When registering on our site, you may be asked to enter your name and e-mail address. You may, however, visit our site without registering. Your e-mail address will be verified by an email containing a unique link. If that link is visited, we know that you control the e-mail address.
-
When registered and posting, we record the IP address that the post originated from. We also may retain server logs which include the IP address of every request to our server.
-
What do we use your information for?
-
Any of the information we collect from you may be used in one of the following ways:
-
-
To personalize your experience — your information helps us to better respond to your individual needs.
-
To improve our site — we continually strive to improve our site offerings based on the information and feedback we receive from you.
-
To improve customer service — your information helps us to more effectively respond to your customer service requests and support needs.
-
To send periodic emails — The email address you provide may be used to send you information, notifications that you request about changes to topics or in response to your user name, respond to inquiries, and/or other requests or questions.
-
-
How do we protect your information?
-
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information.
-
What is your data retention policy?
-
We will make a good faith effort to:
-
-
Retain server logs containing the IP address of all requests to this server no more than 90 days.
-
Retain the IP addresses associated with registered users and their posts no more than 5 years.
-
-
Do we use cookies?
-
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
-
We use cookies to understand and save your preferences for future visits and compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future. We may contract with third-party service providers to assist us in better understanding our site visitors. These service providers are not permitted to use the information collected on our behalf except to help us conduct and improve our business.
-
Do we disclose any information to outside parties?
-
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety. However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
-
Third party links
-
Occasionally, at our discretion, we may include or offer third party products or services on our site. These third party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
Our site, products and services are all directed to people who are at least 13 years old. If this server is in the USA, and you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
-
Online Privacy Policy Only
-
This online privacy policy applies only to information collected through our site and not to information collected offline.
-
Your Consent
-
By using our site, you consent to our web site privacy policy.
-
Changes to our Privacy Policy
-
If we decide to change our privacy policy, we will post those changes on this page.
-
This document is CC-BY-SA. It was last updated May 31, 2013.
title: Условия обслуживания и политика конфиденциальности %{instance}
themes:
default: Mastodon
diff --git a/config/locales/sr-Latn.yml b/config/locales/sr-Latn.yml
index 2d984049a..8d39d35b0 100644
--- a/config/locales/sr-Latn.yml
+++ b/config/locales/sr-Latn.yml
@@ -625,74 +625,6 @@ sr-Latn:
reblogged: podržano
sensitive_content: Osetljiv sadržaj
terms:
- body_html: |
-
Privacy Policy
-
-
What information do we collect?
-
-
We collect information from you when you register on our site and gather data when you participate in the forum by reading, writing, and evaluating the content shared here.
-
-
When registering on our site, you may be asked to enter your name and e-mail address. You may, however, visit our site without registering. Your e-mail address will be verified by an email containing a unique link. If that link is visited, we know that you control the e-mail address.
-
-
When registered and posting, we record the IP address that the post originated from. We also may retain server logs which include the IP address of every request to our server.
-
-
What do we use your information for?
-
-
Any of the information we collect from you may be used in one of the following ways:
-
-
-
To personalize your experience — your information helps us to better respond to your individual needs.
-
To improve our site — we continually strive to improve our site offerings based on the information and feedback we receive from you.
-
To improve customer service — your information helps us to more effectively respond to your customer service requests and support needs.
-
To send periodic emails — The email address you provide may be used to send you information, notifications that you request about changes to topics or in response to your user name, respond to inquiries, and/or other requests or questions.
-
-
-
How do we protect your information?
-
-
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information.
-
-
What is your data retention policy?
-
-
We will make a good faith effort to:
-
-
-
Retain server logs containing the IP address of all requests to this server no more than 90 days.
-
Retain the IP addresses associated with registered users and their posts no more than 5 years.
-
-
-
Do we use cookies?
-
-
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
-
-
We use cookies to understand and save your preferences for future visits and compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future. We may contract with third-party service providers to assist us in better understanding our site visitors. These service providers are not permitted to use the information collected on our behalf except to help us conduct and improve our business.
-
-
Do we disclose any information to outside parties?
-
-
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety. However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
-
-
Third party links
-
-
Occasionally, at our discretion, we may include or offer third party products or services on our site. These third party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
Our site, products and services are all directed to people who are at least 13 years old. If this server is in the USA, and you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
-
-
Online Privacy Policy Only
-
-
This online privacy policy applies only to information collected through our site and not to information collected offline.
-
-
Your Consent
-
-
By using our site, you consent to our web site privacy policy.
-
-
Changes to our Privacy Policy
-
-
If we decide to change our privacy policy, we will post those changes on this page.
-
-
This document is CC-BY-SA. It was last updated May 31, 2013.
We collect information from you when you register on our site and gather data when you participate in the forum by reading, writing, and evaluating the content shared here.
-
-
When registering on our site, you may be asked to enter your name and e-mail address. You may, however, visit our site without registering. Your e-mail address will be verified by an email containing a unique link. If that link is visited, we know that you control the e-mail address.
-
-
When registered and posting, we record the IP address that the post originated from. We also may retain server logs which include the IP address of every request to our server.
-
-
What do we use your information for?
-
-
Any of the information we collect from you may be used in one of the following ways:
-
-
-
To personalize your experience — your information helps us to better respond to your individual needs.
-
To improve our site — we continually strive to improve our site offerings based on the information and feedback we receive from you.
-
To improve customer service — your information helps us to more effectively respond to your customer service requests and support needs.
-
To send periodic emails — The email address you provide may be used to send you information, notifications that you request about changes to topics or in response to your user name, respond to inquiries, and/or other requests or questions.
-
-
-
How do we protect your information?
-
-
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information.
-
-
What is your data retention policy?
-
-
We will make a good faith effort to:
-
-
-
Retain server logs containing the IP address of all requests to this server no more than 90 days.
-
Retain the IP addresses associated with registered users and their posts no more than 5 years.
-
-
-
Do we use cookies?
-
-
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
-
-
We use cookies to understand and save your preferences for future visits and compile aggregate data about site traffic and site interaction so that we can offer better site experiences and tools in the future. We may contract with third-party service providers to assist us in better understanding our site visitors. These service providers are not permitted to use the information collected on our behalf except to help us conduct and improve our business.
-
-
Do we disclose any information to outside parties?
-
-
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety. However, non-personally identifiable visitor information may be provided to other parties for marketing, advertising, or other uses.
-
-
Third party links
-
-
Occasionally, at our discretion, we may include or offer third party products or services on our site. These third party sites have separate and independent privacy policies. We therefore have no responsibility or liability for the content and activities of these linked sites. Nonetheless, we seek to protect the integrity of our site and welcome any feedback about these sites.
Our site, products and services are all directed to people who are at least 13 years old. If this server is in the USA, and you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
-
-
Online Privacy Policy Only
-
-
This online privacy policy applies only to information collected through our site and not to information collected offline.
-
-
Your Consent
-
-
By using our site, you consent to our web site privacy policy.
-
-
Changes to our Privacy Policy
-
-
If we decide to change our privacy policy, we will post those changes on this page.
-
-
This document is CC-BY-SA. It was last updated May 31, 2013.
title: Услови коришћења и политика приватности инстанце %{instance}
themes:
default: Мастодонт
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 8ce6b3100..f85ed6efb 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -656,74 +656,6 @@ sv:
reblogged: boostad
sensitive_content: Känsligt innehåll
terms:
- body_html: |
-
Integritetspolicy
-
-
Vilken information samlar vi in
-
-
Vi samlar in information från dig när du registrerar dig på vår webbplats och samlar in data när du deltar i forumet genom att läsa, skriva och utvärdera innehållet som delas här.
-
-
När du registrerar dig på vår webbplats kan du bli ombedd att ange ditt namn och din e-postadress. Du kan dock besöka vår webbplats utan att registrera dig. Din e-postadress kommer att verifieras med ett e-postmeddelande som innehåller en unik länk. Om den länken besöks vet vi att du kontrollerar e-postadressen.
-
-
När vi registrerar och postar registrerar vi den IP-adress som posten härstammar från. Vi kan också behålla serverns loggar som innehåller IP-adress för varje begäran till vår server.
-
-
Vad använder vi din information för?
-
-
Vilken som helst information vi samlar in från dig kan användas på något av följande sätt:
-
-
-
För att personifiera din upplevelse — Din information hjälper oss att bättre svara på dina individuella behov.
-
För att förbättra vår webbplats — Vi strävar kontinuerligt efter att förbättra våra erbjudanden på webbplatsen baserat på information och feedback vi mottar från dig.
-
För att förbättra kundtjänst — Din information hjälper oss att effektivt svara på dina kundserviceförfrågningar och supportbehov.
-
För att skicka periodiska e-postmeddelanden — Den e-postadress du anger kan användas för att skicka information, meddelanden som du begär om ändringar i ämnen eller som svar på ditt användarnamn, svara på förfrågningar och / eller andra förfrågningar eller frågor.
-
-
-
Hur skyddar vi din information?
-
-
Vi genomför en rad säkerhetsåtgärder för att upprätthålla säkerheten för din personliga information när du anger, lämnar in eller har tillgång till din personliga information.
-
-
Vad är policyn för lagring av data?
-
-
Vi kommer att göra en ansträngning för:
-
-
-
Behåll serverloggar som innehåller IP-adressen för alla förfrågningar till den här servern inte mer än 90 dagar.
-
Behåll IP-adresserna i samband med registrerade användare och deras inlägg inte längre än 5 år.
-
-
-
Använder vi cookies?
-
-
Ja. Cookies är små filer som en webbplats eller tjänstleverantör överför till datorns hårddisk via din webbläsare (om du tillåter). Dessa cookies tillåter webbplatsen att känna igen din webbläsare och, om du har ett registrerat konto, associerar det med ditt registrerade konto.
-
-
Vi använder cookies för att förstå och spara dina inställningar för framtida besök och sammanställa sammanlagda data om webbplatsstrafik och webbplatsinteraktion så att vi kan erbjuda bättre sajtupplevelser och verktyg i framtiden. Vi kan komma överens med tredje parts tjänsteleverantörer för att hjälpa oss att bättre förstå våra besökare. Dessa tjänsteleverantörer får inte använda den information som samlas in för vår räkning utom för att hjälpa oss att bedriva och förbättra vår verksamhet.
-
-
Avslöjar vi information till utomstående parter?
-
-
Vi säljer inte, handlar eller på annat sätt överför dina personuppgifter till utomstående parter. Det här omfattar inte betrodda tredje parter som hjälper oss att driva vår webbplats, bedriva vår verksamhet eller service dig, så länge dessa parter är överens om att hålla denna information konfidentiell. Vi kan också släppa din information när vi anser att utgåvan är lämplig för att följa lagen, tillämpa vår webbplatspolicy eller skydda vår eller andra rättigheter, egendom eller säkerhet. Däremot kan personuppgifter som inte identifieras personligen lämnas till andra parter för marknadsföring, reklam eller annan användning.
-
-
Tredjepartslänkar
-
-
Ibland kan vi, efter eget gottfinnande, inkludera eller erbjuda produkter från tredje part eller tjänster på vår webbplats. Dessa tredje parts webbplatser har separata och oberoende sekretesspolicyer. Vi har därför inget ansvar eller ansvar för innehållet och aktiviteterna för dessa länkade webbplatser. Ändå försöker vi skydda integriteten på vår webbplats och välkomna eventuella återkopplingar om dessa webbplatser.
Vår webbplats, produkter och tjänster riktas alla till personer som är minst 13 år gamla. Om den här servern är i USA, och du är under 13 år, enligt kraven i COPPA (Children's Online Privacy Protection Act) ska du inte använda denna sida.
-
-
Endast online sekretesspolicy
-
-
Denna online sekretesspolicy gäller endast information som samlas in via vår webbplats och inte till information som samlas in offline.
-
-
Ditt samtycke
-
-
Genom att använda vår webbplats godkänner du vår hemsida sekretesspolicy.
-
-
Ändringar i vår sekretesspolicy
-
-
Om vi bestämmer oss för att ändra vår integritetspolicy, lägger vi in de ändringar på den här sidan.
-
-
This document is CC-BY-SA. It was last updated May 31, 2013.
title: "%{instance} 使用条款和隐私权政策"
time:
formats:
From b08ab329f4d149fd414e0539574f49062c571a8a Mon Sep 17 00:00:00 2001
From: Isatis <515462+Reverite@users.noreply.github.com>
Date: Wed, 4 Apr 2018 13:25:34 -0700
Subject: [PATCH 043/442] retrieve custom emoji list via API instead of before
page load (#7047)
---
.../mastodon/actions/custom_emojis.js | 37 +++++++++++++++++++
.../mastodon/containers/mastodon.js | 4 ++
.../mastodon/reducers/custom_emojis.js | 17 ++++-----
app/serializers/initial_state_serializer.rb | 6 ---
4 files changed, 49 insertions(+), 15 deletions(-)
create mode 100644 app/javascript/mastodon/actions/custom_emojis.js
diff --git a/app/javascript/mastodon/actions/custom_emojis.js b/app/javascript/mastodon/actions/custom_emojis.js
new file mode 100644
index 000000000..aa37bc423
--- /dev/null
+++ b/app/javascript/mastodon/actions/custom_emojis.js
@@ -0,0 +1,37 @@
+import api from '../api';
+
+export const CUSTOM_EMOJIS_FETCH_REQUEST = 'CUSTOM_EMOJIS_FETCH_REQUEST';
+export const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS';
+export const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL';
+
+export function fetchCustomEmojis() {
+ return (dispatch, getState) => {
+ dispatch(fetchCustomEmojisRequest());
+
+ api(getState).get('/api/v1/custom_emojis').then(response => {
+ dispatch(fetchCustomEmojisSuccess(response.data));
+ }).catch(error => {
+ dispatch(fetchCustomEmojisFail(error));
+ });
+ };
+};
+
+export function fetchCustomEmojisRequest() {
+ return {
+ type: CUSTOM_EMOJIS_FETCH_REQUEST,
+ };
+};
+
+export function fetchCustomEmojisSuccess(custom_emojis) {
+ return {
+ type: CUSTOM_EMOJIS_FETCH_SUCCESS,
+ custom_emojis,
+ };
+};
+
+export function fetchCustomEmojisFail(error) {
+ return {
+ type: CUSTOM_EMOJIS_FETCH_FAIL,
+ error,
+ };
+};
diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js
index d1710445b..b29898d3b 100644
--- a/app/javascript/mastodon/containers/mastodon.js
+++ b/app/javascript/mastodon/containers/mastodon.js
@@ -6,6 +6,7 @@ import { showOnboardingOnce } from '../actions/onboarding';
import { BrowserRouter, Route } from 'react-router-dom';
import { ScrollContext } from 'react-router-scroll-4';
import UI from '../features/ui';
+import { fetchCustomEmojis } from '../actions/custom_emojis';
import { hydrateStore } from '../actions/store';
import { connectUserStream } from '../actions/streaming';
import { IntlProvider, addLocaleData } from 'react-intl';
@@ -19,6 +20,9 @@ export const store = configureStore();
const hydrateAction = hydrateStore(initialState);
store.dispatch(hydrateAction);
+// load custom emojis
+store.dispatch(fetchCustomEmojis());
+
export default class Mastodon extends React.PureComponent {
static propTypes = {
diff --git a/app/javascript/mastodon/reducers/custom_emojis.js b/app/javascript/mastodon/reducers/custom_emojis.js
index 307bcc7dc..d2c801ade 100644
--- a/app/javascript/mastodon/reducers/custom_emojis.js
+++ b/app/javascript/mastodon/reducers/custom_emojis.js
@@ -1,16 +1,15 @@
-import { List as ImmutableList } from 'immutable';
-import { STORE_HYDRATE } from '../actions/store';
+import { List as ImmutableList, fromJS as ConvertToImmutable } from 'immutable';
+import { CUSTOM_EMOJIS_FETCH_SUCCESS } from '../actions/custom_emojis';
import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
import { buildCustomEmojis } from '../features/emoji/emoji';
-const initialState = ImmutableList();
+const initialState = ImmutableList([]);
export default function custom_emojis(state = initialState, action) {
- switch(action.type) {
- case STORE_HYDRATE:
- emojiSearch('', { custom: buildCustomEmojis(action.state.get('custom_emojis', [])) });
- return action.state.get('custom_emojis');
- default:
- return state;
+ if(action.type === CUSTOM_EMOJIS_FETCH_SUCCESS) {
+ state = ConvertToImmutable(action.custom_emojis);
+ emojiSearch('', { custom: buildCustomEmojis(state) });
}
+
+ return state;
};
diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb
index 216cf5446..3b908e224 100644
--- a/app/serializers/initial_state_serializer.rb
+++ b/app/serializers/initial_state_serializer.rb
@@ -4,12 +4,6 @@ class InitialStateSerializer < ActiveModel::Serializer
attributes :meta, :compose, :accounts,
:media_attachments, :settings, :push_subscription
- has_many :custom_emojis, serializer: REST::CustomEmojiSerializer
-
- def custom_emojis
- CustomEmoji.local.where(disabled: false)
- end
-
def meta
store = {
streaming_api_base_url: Rails.configuration.x.streaming_api_base_url,
From 98146281e1beaf994710b13ef70f6224e8588cba Mon Sep 17 00:00:00 2001
From: Harmon
Date: Sat, 7 Apr 2018 07:53:11 -0500
Subject: [PATCH 044/442] Remove duplicate frequently used emojis (#7064)
---
.../compose/containers/emoji_picker_dropdown_container.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js b/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js
index e6a535a5d..5ec937a39 100644
--- a/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js
+++ b/app/javascript/mastodon/features/compose/containers/emoji_picker_dropdown_container.js
@@ -38,7 +38,8 @@ const getFrequentlyUsedEmojis = createSelector([
.toArray();
if (emojis.length < DEFAULTS.length) {
- emojis = emojis.concat(DEFAULTS.slice(0, DEFAULTS.length - emojis.length));
+ let uniqueDefaults = DEFAULTS.filter(emoji => !emojis.includes(emoji));
+ emojis = emojis.concat(uniqueDefaults.slice(0, DEFAULTS.length - emojis.length));
}
return emojis;
From b5726def55994db8eb5797bbea1d2b79df3e884a Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Sat, 7 Apr 2018 18:54:46 +0200
Subject: [PATCH 045/442] Forward deletes on the same path as reply forwarding
(#7058)
* Forward deletes on the same path as reply forwarding
* Remove trailing whitespace
---
app/lib/activitypub/activity/delete.rb | 36 +++++++++++++++++++-------
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/app/lib/activitypub/activity/delete.rb b/app/lib/activitypub/activity/delete.rb
index 5fa60a81c..3474d55d9 100644
--- a/app/lib/activitypub/activity/delete.rb
+++ b/app/lib/activitypub/activity/delete.rb
@@ -17,21 +17,25 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
end
def delete_note
- status = Status.find_by(uri: object_uri, account: @account)
- status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?
+ @status = Status.find_by(uri: object_uri, account: @account)
+ @status ||= Status.find_by(uri: @object['atomUri'], account: @account) if @object.is_a?(Hash) && @object['atomUri'].present?
delete_later!(object_uri)
- return if status.nil?
+ return if @status.nil?
- forward_for_reblogs(status)
- delete_now!(status)
+ if @status.public_visibility? || @status.unlisted_visibility?
+ forward_for_reply
+ forward_for_reblogs
+ end
+
+ delete_now!
end
- def forward_for_reblogs(status)
+ def forward_for_reblogs
return if @json['signature'].blank?
- rebloggers_ids = status.reblogs.includes(:account).references(:account).merge(Account.local).pluck(:account_id)
+ rebloggers_ids = @status.reblogs.includes(:account).references(:account).merge(Account.local).pluck(:account_id)
inboxes = Account.where(id: ::Follow.where(target_account_id: rebloggers_ids).select(:account_id)).inboxes - [@account.preferred_inbox_url]
ActivityPub::DeliveryWorker.push_bulk(inboxes) do |inbox_url|
@@ -39,8 +43,22 @@ class ActivityPub::Activity::Delete < ActivityPub::Activity
end
end
- def delete_now!(status)
- RemoveStatusService.new.call(status)
+ def replied_to_status
+ return @replied_to_status if defined?(@replied_to_status)
+ @replied_to_status = @status.thread
+ end
+
+ def reply_to_local?
+ !replied_to_status.nil? && replied_to_status.account.local?
+ end
+
+ def forward_for_reply
+ return unless @json['signature'].present? && reply_to_local?
+ ActivityPub::RawDistributionWorker.perform_async(Oj.dump(@json), replied_to_status.account_id, [@account.preferred_inbox_url])
+ end
+
+ def delete_now!
+ RemoveStatusService.new.call(@status)
end
def payload
From b65eb00c53af939444e0e891c0a3a4563f4897ac Mon Sep 17 00:00:00 2001
From: Alda Marteau-Hardi
Date: Sat, 7 Apr 2018 21:33:01 +0200
Subject: [PATCH 046/442] Prevent admins and moderators eavesdropping in
private and direct toots (#7067)
Fix #6986
---
app/controllers/admin/statuses_controller.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/controllers/admin/statuses_controller.rb b/app/controllers/admin/statuses_controller.rb
index 5d4325f57..d5787acfb 100644
--- a/app/controllers/admin/statuses_controller.rb
+++ b/app/controllers/admin/statuses_controller.rb
@@ -12,7 +12,7 @@ module Admin
def index
authorize :status, :index?
- @statuses = @account.statuses
+ @statuses = @account.statuses.where(visibility: [:public, :unlisted])
if params[:media]
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
From 4a9becfca2d7399acb422da646c48bdd9f39c989 Mon Sep 17 00:00:00 2001
From: Hisham Muhammad
Date: Sat, 7 Apr 2018 16:36:03 -0300
Subject: [PATCH 047/442] i18n: improve "Welcome" translation in Portuguese
(#7068)
* i18n: update gender-neutral language for pt and pt-BR
Instead of using "bem-vindo(a)" (a masculine form of "Welcome"
with a "(a)" in the end to mean "bem-vinda" for the feminine form),
use "boas-vindas", which is a gender-neutral form of "Welcome").
There is already precedent for using "boas-vindas" in the
Brazilian Portuguese localization, in `config/locales/pt-BR.yml`.
European Portuguese dictionary Priberam also registers it as a valid form:
https://www.priberam.pt/dlpo/boas-vindas
* i18n: pt-BR minor orthography fix
The form "a bordo" does not take an accent.
http://oredator.com.br/curso-de-redacao/uncategorized/a-bordo-ou-a-bordo
---
app/javascript/mastodon/locales/pt-BR.json | 2 +-
app/javascript/mastodon/locales/pt.json | 2 +-
config/locales/pt-BR.yml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index b056ec8bd..4cd2e0643 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -189,7 +189,7 @@
"onboarding.page_one.federation": "Mastodon é uma rede de servidores independentes que se juntam para fazer uma grande rede social. Nós chamamos estes servidores de instâncias.",
"onboarding.page_one.full_handle": "Seu nome de usuário completo",
"onboarding.page_one.handle_hint": "Isso é o que você diz aos seus amigos para que eles possam te mandar mensagens ou te seguir a partir de outra instância.",
- "onboarding.page_one.welcome": "Seja bem-vindo(a) ao Mastodon!",
+ "onboarding.page_one.welcome": "Boas-vindas ao Mastodon!",
"onboarding.page_six.admin": "O administrador de sua instância é {admin}.",
"onboarding.page_six.almost_done": "Quase acabando...",
"onboarding.page_six.appetoot": "Bom Apetoot!",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index 65983000c..7a404eaba 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -189,7 +189,7 @@
"onboarding.page_one.federation": "Mastodon é uma rede de servidores independentes ligados entre si para fazer uma grande rede social. Nós chamamos instâncias a estes servidores.",
"onboarding.page_one.full_handle": "O teu nome de utilizador completo",
"onboarding.page_one.handle_hint": "Isto é o que dizes aos teus amigos para pesquisar.",
- "onboarding.page_one.welcome": "Bem-vindo(a) ao Mastodon!",
+ "onboarding.page_one.welcome": "Boas-vindas ao Mastodon!",
"onboarding.page_six.admin": "O administrador da tua instância é {admin}.",
"onboarding.page_six.almost_done": "Quase pronto...",
"onboarding.page_six.appetoot": "Bon Appetoot!",
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index c1225d356..d6f463a19 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -709,7 +709,7 @@ pt-BR:
tip_local_timeline: A timeline local é uma visão contínua das pessoas que estão em %{instance}. Esses são seus vizinhos próximos!
tip_mobile_webapp: Se o seu navegador móvel oferecer a opção de adicionar Mastodon à tela inicial, você pode receber notificações push. Vai funcionar quase como um aplicativo nativo!
tips: Dicas
- title: Boas-vindas à bordo, %{name}!
+ title: Boas-vindas a bordo, %{name}!
users:
invalid_email: O endereço de e-mail é inválido
invalid_otp_token: Código de autenticação inválido
From d4de2239b0ab04bf6a42db9f28d1fdd8e45f7d8b Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Sat, 7 Apr 2018 21:36:58 +0200
Subject: [PATCH 048/442] Add a circuit breaker for ActivityPub deliveries
(#7053)
---
Gemfile | 2 ++
Gemfile.lock | 2 ++
app/workers/activitypub/delivery_worker.rb | 14 +++++++++-----
config/initializers/stoplight.rb | 3 +++
4 files changed, 16 insertions(+), 5 deletions(-)
create mode 100644 config/initializers/stoplight.rb
diff --git a/Gemfile b/Gemfile
index 9e644e7ae..4a5a166bd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -35,6 +35,7 @@ gem 'devise-two-factor', '~> 3.0'
group :pam_authentication, optional: true do
gem 'devise_pam_authenticatable2', '~> 9.0'
end
+
gem 'net-ldap', '~> 0.10'
gem 'omniauth-cas', '~> 1.1'
gem 'omniauth-saml', '~> 1.10'
@@ -79,6 +80,7 @@ gem 'sidekiq-bulk', '~>0.1.1'
gem 'simple-navigation', '~> 4.0'
gem 'simple_form', '~> 3.4'
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
+gem 'stoplight', '~> 2.1.3'
gem 'strong_migrations'
gem 'tty-command'
gem 'tty-prompt'
diff --git a/Gemfile.lock b/Gemfile.lock
index a185a602e..0f5a1fb6a 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -550,6 +550,7 @@ GEM
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
statsd-ruby (1.2.1)
+ stoplight (2.1.3)
streamio-ffmpeg (3.0.2)
multi_json (~> 1.8)
strong_migrations (0.1.9)
@@ -716,6 +717,7 @@ DEPENDENCIES
simple_form (~> 3.4)
simplecov (~> 0.14)
sprockets-rails (~> 3.2)
+ stoplight (~> 2.1.3)
streamio-ffmpeg (~> 3.0)
strong_migrations
tty-command
diff --git a/app/workers/activitypub/delivery_worker.rb b/app/workers/activitypub/delivery_worker.rb
index e6cfd0d07..adffd1d3b 100644
--- a/app/workers/activitypub/delivery_worker.rb
+++ b/app/workers/activitypub/delivery_worker.rb
@@ -12,9 +12,7 @@ class ActivityPub::DeliveryWorker
@source_account = Account.find(source_account_id)
@inbox_url = inbox_url
- perform_request do |response|
- raise Mastodon::UnexpectedResponseError, response unless response_successful? response
- end
+ perform_request
failure_tracker.track_success!
rescue => e
@@ -30,8 +28,14 @@ class ActivityPub::DeliveryWorker
request.add_headers(HEADERS)
end
- def perform_request(&block)
- build_request.perform(&block)
+ def perform_request
+ light = Stoplight(@inbox_url) do
+ build_request.perform do |response|
+ raise Mastodon::UnexpectedResponseError, response unless response_successful?(response)
+ end
+ end
+
+ light.run
end
def response_successful?(response)
diff --git a/config/initializers/stoplight.rb b/config/initializers/stoplight.rb
new file mode 100644
index 000000000..1bd4ee6e7
--- /dev/null
+++ b/config/initializers/stoplight.rb
@@ -0,0 +1,3 @@
+require 'stoplight'
+
+Stoplight::Light.default_data_store = Stoplight::DataStore::Redis.new(Redis.current)
From b83ce18b30d33c30b461f593ac4cd6e86057a365 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?THE=20BOSS=20=E2=99=A8?=
<30565780+theboss@users.noreply.github.com>
Date: Sun, 8 Apr 2018 16:57:16 +0900
Subject: [PATCH 049/442] Ignore elasticsearch directory (#7070)
---
.dockerignore | 1 +
.gitignore | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/.dockerignore b/.dockerignore
index 5cd3b179a..5fb9861de 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -11,3 +11,4 @@ vendor/bundle
*~
postgres
redis
+elasticsearch
diff --git a/.gitignore b/.gitignore
index 38ebc934f..51e47bb52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,9 +36,10 @@ config/deploy/*
.vscode/
.idea/
-# Ignore postgres + redis volume optionally created by docker-compose
+# Ignore postgres + redis + elasticsearch volume optionally created by docker-compose
postgres
redis
+elasticsearch
# Ignore Apple files
.DS_Store
From 1ed1014546bcfef0d2441702673deab586f6bca0 Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Sun, 8 Apr 2018 20:32:39 +0900
Subject: [PATCH 050/442] Free stroage if it is exceeding disk quota (#7061)
---
app/javascript/mastodon/actions/accounts.js | 9 ++-
.../mastodon/actions/importer/index.js | 3 +-
app/javascript/mastodon/actions/statuses.js | 11 ++-
.../mastodon/service_worker/entry.js | 13 ++-
app/javascript/mastodon/storage/db.js | 9 +--
app/javascript/mastodon/storage/modifier.js | 80 ++++++++++++++-----
6 files changed, 89 insertions(+), 36 deletions(-)
diff --git a/app/javascript/mastodon/actions/accounts.js b/app/javascript/mastodon/actions/accounts.js
index 28ae56763..c9e4afcfc 100644
--- a/app/javascript/mastodon/actions/accounts.js
+++ b/app/javascript/mastodon/actions/accounts.js
@@ -1,5 +1,5 @@
import api, { getLinks } from '../api';
-import asyncDB from '../storage/db';
+import openDB from '../storage/db';
import { importAccount, importFetchedAccount, importFetchedAccounts } from './importer';
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
@@ -94,12 +94,15 @@ export function fetchAccount(id) {
dispatch(fetchAccountRequest(id));
- asyncDB.then(db => getFromDB(
+ openDB().then(db => getFromDB(
dispatch,
getState,
db.transaction('accounts', 'read').objectStore('accounts').index('id'),
id
- )).catch(() => api(getState).get(`/api/v1/accounts/${id}`).then(response => {
+ ).then(() => db.close(), error => {
+ db.close();
+ throw error;
+ })).catch(() => api(getState).get(`/api/v1/accounts/${id}`).then(response => {
dispatch(importFetchedAccount(response.data));
})).then(() => {
dispatch(fetchAccountSuccess());
diff --git a/app/javascript/mastodon/actions/importer/index.js b/app/javascript/mastodon/actions/importer/index.js
index e671d417c..5b18cbc1d 100644
--- a/app/javascript/mastodon/actions/importer/index.js
+++ b/app/javascript/mastodon/actions/importer/index.js
@@ -1,3 +1,4 @@
+import { autoPlayGif } from '../../initial_state';
import { putAccounts, putStatuses } from '../../storage/modifier';
import { normalizeAccount, normalizeStatus } from './normalizer';
@@ -44,7 +45,7 @@ export function importFetchedAccounts(accounts) {
}
accounts.forEach(processAccount);
- putAccounts(normalAccounts);
+ putAccounts(normalAccounts, !autoPlayGif);
return importAccounts(normalAccounts);
}
diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js
index d28aef880..849cb4f5a 100644
--- a/app/javascript/mastodon/actions/statuses.js
+++ b/app/javascript/mastodon/actions/statuses.js
@@ -1,5 +1,5 @@
import api from '../api';
-import asyncDB from '../storage/db';
+import openDB from '../storage/db';
import { evictStatus } from '../storage/modifier';
import { deleteFromTimelines } from './timelines';
@@ -92,12 +92,17 @@ export function fetchStatus(id) {
dispatch(fetchStatusRequest(id, skipLoading));
- asyncDB.then(db => {
+ openDB().then(db => {
const transaction = db.transaction(['accounts', 'statuses'], 'read');
const accountIndex = transaction.objectStore('accounts').index('id');
const index = transaction.objectStore('statuses').index('id');
- return getFromDB(dispatch, getState, accountIndex, index, id);
+ return getFromDB(dispatch, getState, accountIndex, index, id).then(() => {
+ db.close();
+ }, error => {
+ db.close();
+ throw error;
+ });
}).then(() => {
dispatch(fetchStatusSuccess(skipLoading));
}, () => api(getState).get(`/api/v1/statuses/${id}`).then(response => {
diff --git a/app/javascript/mastodon/service_worker/entry.js b/app/javascript/mastodon/service_worker/entry.js
index 160c3fbf2..ba54ae996 100644
--- a/app/javascript/mastodon/service_worker/entry.js
+++ b/app/javascript/mastodon/service_worker/entry.js
@@ -1,3 +1,4 @@
+import { freeStorage } from '../storage/modifier';
import './web_push_notifications';
function openSystemCache() {
@@ -42,8 +43,10 @@ self.addEventListener('fetch', function(event) {
event.respondWith(asyncResponse.then(async response => {
if (response.ok || response.type === 'opaqueredirect') {
- const cache = await asyncCache;
- await cache.delete('/');
+ await Promise.all([
+ asyncCache.then(cache => cache.delete('/')),
+ indexedDB.deleteDatabase('mastodon'),
+ ]);
}
return response;
@@ -56,7 +59,11 @@ self.addEventListener('fetch', function(event) {
const fetched = await fetch(event.request);
if (fetched.ok) {
- await cache.put(event.request.url, fetched.clone());
+ try {
+ await cache.put(event.request.url, fetched.clone());
+ } finally {
+ freeStorage();
+ }
}
return fetched;
diff --git a/app/javascript/mastodon/storage/db.js b/app/javascript/mastodon/storage/db.js
index e08fc3f3d..377a792a7 100644
--- a/app/javascript/mastodon/storage/db.js
+++ b/app/javascript/mastodon/storage/db.js
@@ -1,15 +1,14 @@
-import { me } from '../initial_state';
-
-export default new Promise((resolve, reject) => {
+export default () => new Promise((resolve, reject) => {
+ // ServiceWorker is required to synchronize the login state.
// Microsoft Edge 17 does not support getAll according to:
// Catalog of standard and vendor APIs across browsers - Microsoft Edge Development
// https://developer.microsoft.com/en-us/microsoft-edge/platform/catalog/?q=specName%3Aindexeddb
- if (!me || !('getAll' in IDBObjectStore.prototype)) {
+ if (!('caches' in self && 'getAll' in IDBObjectStore.prototype)) {
reject();
return;
}
- const request = indexedDB.open('mastodon:' + me);
+ const request = indexedDB.open('mastodon');
request.onerror = reject;
request.onsuccess = ({ target }) => resolve(target.result);
diff --git a/app/javascript/mastodon/storage/modifier.js b/app/javascript/mastodon/storage/modifier.js
index 4773d07a9..c2ed6f807 100644
--- a/app/javascript/mastodon/storage/modifier.js
+++ b/app/javascript/mastodon/storage/modifier.js
@@ -1,13 +1,14 @@
-import asyncDB from './db';
-import { autoPlayGif } from '../initial_state';
+import openDB from './db';
const accountAssetKeys = ['avatar', 'avatar_static', 'header', 'header_static'];
-const avatarKey = autoPlayGif ? 'avatar' : 'avatar_static';
-const limit = 1024;
+const storageMargin = 8388608;
+const storeLimit = 1024;
-// ServiceWorker and Cache API is not available on iOS 11
-// https://webkit.org/status/#specification-service-workers
-const asyncCache = window.caches ? caches.open('mastodon-system') : Promise.reject();
+function openCache() {
+ // ServiceWorker and Cache API is not available on iOS 11
+ // https://webkit.org/status/#specification-service-workers
+ return self.caches ? caches.open('mastodon-system') : Promise.reject();
+}
function printErrorIfAvailable(error) {
if (error) {
@@ -16,7 +17,7 @@ function printErrorIfAvailable(error) {
}
function put(name, objects, onupdate, oncreate) {
- return asyncDB.then(db => new Promise((resolve, reject) => {
+ return openDB().then(db => (new Promise((resolve, reject) => {
const putTransaction = db.transaction(name, 'readwrite');
const putStore = putTransaction.objectStore(name);
const putIndex = putStore.index('id');
@@ -53,7 +54,7 @@ function put(name, objects, onupdate, oncreate) {
const count = readStore.count();
count.onsuccess = () => {
- const excess = count.result - limit;
+ const excess = count.result - storeLimit;
if (excess > 0) {
const retrieval = readStore.getAll(null, excess);
@@ -69,11 +70,17 @@ function put(name, objects, onupdate, oncreate) {
};
putTransaction.onerror = reject;
+ })).then(resolved => {
+ db.close();
+ return resolved;
+ }, error => {
+ db.close();
+ throw error;
}));
}
function evictAccountsByRecords(records) {
- asyncDB.then(db => {
+ return openDB().then(db => {
const transaction = db.transaction(['accounts', 'statuses'], 'readwrite');
const accounts = transaction.objectStore('accounts');
const accountsIdIndex = accounts.index('id');
@@ -83,7 +90,7 @@ function evictAccountsByRecords(records) {
function evict(toEvict) {
toEvict.forEach(record => {
- asyncCache
+ openCache()
.then(cache => accountAssetKeys.forEach(key => cache.delete(records[key])))
.catch(printErrorIfAvailable);
@@ -98,6 +105,8 @@ function evictAccountsByRecords(records) {
}
evict(records);
+
+ db.close();
}).catch(printErrorIfAvailable);
}
@@ -106,8 +115,9 @@ export function evictStatus(id) {
}
export function evictStatuses(ids) {
- asyncDB.then(db => {
- const store = db.transaction('statuses', 'readwrite').objectStore('statuses');
+ return openDB().then(db => {
+ const transaction = db.transaction('statuses', 'readwrite');
+ const store = transaction.objectStore('statuses');
const idIndex = store.index('id');
const reblogIndex = store.index('reblog');
@@ -118,14 +128,17 @@ export function evictStatuses(ids) {
idIndex.getKey(id).onsuccess =
({ target }) => target.result && store.delete(target.result);
});
+
+ db.close();
}).catch(printErrorIfAvailable);
}
function evictStatusesByRecords(records) {
- evictStatuses(records.map(({ id }) => id));
+ return evictStatuses(records.map(({ id }) => id));
}
-export function putAccounts(records) {
+export function putAccounts(records, avatarStatic) {
+ const avatarKey = avatarStatic ? 'avatar_static' : 'avatar';
const newURLs = [];
put('accounts', records, (newRecord, oldKey, store, oncomplete) => {
@@ -135,7 +148,7 @@ export function putAccounts(records) {
const oldURL = target.result[key];
if (newURL !== oldURL) {
- asyncCache
+ openCache()
.then(cache => cache.delete(oldURL))
.catch(printErrorIfAvailable);
}
@@ -153,11 +166,12 @@ export function putAccounts(records) {
}, (newRecord, oncomplete) => {
newURLs.push(newRecord[avatarKey]);
oncomplete();
- }).then(records => {
- evictAccountsByRecords(records);
- asyncCache
- .then(cache => cache.addAll(newURLs))
- .catch(printErrorIfAvailable);
+ }).then(records => Promise.all([
+ evictAccountsByRecords(records),
+ openCache().then(cache => cache.addAll(newURLs)),
+ ])).then(freeStorage, error => {
+ freeStorage();
+ throw error;
}).catch(printErrorIfAvailable);
}
@@ -166,3 +180,27 @@ export function putStatuses(records) {
.then(evictStatusesByRecords)
.catch(printErrorIfAvailable);
}
+
+export function freeStorage() {
+ return navigator.storage.estimate().then(({ quota, usage }) => {
+ if (usage + storageMargin < quota) {
+ return null;
+ }
+
+ return openDB().then(db => new Promise((resolve, reject) => {
+ const retrieval = db.transaction('accounts', 'readonly').objectStore('accounts').getAll(null, 1);
+
+ retrieval.onsuccess = () => {
+ if (retrieval.result.length > 0) {
+ resolve(evictAccountsByRecords(retrieval.result).then(freeStorage));
+ } else {
+ resolve(caches.delete('mastodon-system'));
+ }
+ };
+
+ retrieval.onerror = reject;
+
+ db.close();
+ }));
+ });
+}
From 1364e9e4ae1fb12a1c970795f1d0afd651c7cfe2 Mon Sep 17 00:00:00 2001
From: ThibG
Date: Sun, 8 Apr 2018 13:40:22 +0200
Subject: [PATCH 051/442] Fix follow/unfollow buttons on public profile (fixes
#7036) (#7040)
* Fix follow/unfollow buttons on public profile
- Present non-logged users with web+mastodon:// URLs for remote accounts
- Present logged-in users with appropriate links (authorize_follows and
remote_unfollows) for remote accounts
* Do not cache rendered cards if user is logged in
---
.../remote_account_controller_concern.rb | 21 ++++++++++
app/controllers/remote_unfollows.rb | 39 +++++++++++++++++++
app/views/accounts/_follow_button.html.haml | 6 +--
app/views/accounts/_follow_grid.html.haml | 2 +-
app/views/remote_unfollows/_card.html.haml | 13 +++++++
.../_post_follow_actions.html.haml | 4 ++
app/views/remote_unfollows/error.html.haml | 3 ++
app/views/remote_unfollows/success.html.haml | 10 +++++
config/routes.rb | 1 +
9 files changed, 95 insertions(+), 4 deletions(-)
create mode 100644 app/controllers/concerns/remote_account_controller_concern.rb
create mode 100644 app/controllers/remote_unfollows.rb
create mode 100644 app/views/remote_unfollows/_card.html.haml
create mode 100644 app/views/remote_unfollows/_post_follow_actions.html.haml
create mode 100644 app/views/remote_unfollows/error.html.haml
create mode 100644 app/views/remote_unfollows/success.html.haml
diff --git a/app/controllers/concerns/remote_account_controller_concern.rb b/app/controllers/concerns/remote_account_controller_concern.rb
new file mode 100644
index 000000000..e17910642
--- /dev/null
+++ b/app/controllers/concerns/remote_account_controller_concern.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module RemoteAccountControllerConcern
+ extend ActiveSupport::Concern
+
+ included do
+ layout 'public'
+ before_action :set_account
+ before_action :check_account_suspension
+ end
+
+ private
+
+ def set_account
+ @account = Account.find_remote!(params[:acct])
+ end
+
+ def check_account_suspension
+ gone if @account.suspended?
+ end
+end
diff --git a/app/controllers/remote_unfollows.rb b/app/controllers/remote_unfollows.rb
new file mode 100644
index 000000000..af5943363
--- /dev/null
+++ b/app/controllers/remote_unfollows.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class RemoteUnfollowsController < ApplicationController
+ layout 'modal'
+
+ before_action :authenticate_user!
+ before_action :set_body_classes
+
+ def create
+ @account = unfollow_attempt.try(:target_account)
+
+ if @account.nil?
+ render :error
+ else
+ render :success
+ end
+ rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
+ render :error
+ end
+
+ private
+
+ def unfollow_attempt
+ username, domain = acct_without_prefix.split('@')
+ UnfollowService.new.call(current_account, Account.find_remote!(username, domain))
+ end
+
+ def acct_without_prefix
+ acct_params.gsub(/\Aacct:/, '')
+ end
+
+ def acct_params
+ params.fetch(:acct, '')
+ end
+
+ def set_body_classes
+ @body_classes = 'modal-layout'
+ end
+end
diff --git a/app/views/accounts/_follow_button.html.haml b/app/views/accounts/_follow_button.html.haml
index e476e0aff..96ae23234 100644
--- a/app/views/accounts/_follow_button.html.haml
+++ b/app/views/accounts/_follow_button.html.haml
@@ -8,16 +8,16 @@
- if user_signed_in? && current_account.id != account.id && !requested
.controls
- if following
- = link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do
+ = link_to (account.local? ? account_unfollow_path(account) : remote_unfollow_path(acct: account.acct)), data: { method: :post }, class: 'icon-button' do
= fa_icon 'user-times'
= t('accounts.unfollow')
- else
- = link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do
+ = link_to (account.local? ? account_follow_path(account) : authorize_follow_path(acct: account.acct)), data: { method: :post }, class: 'icon-button' do
= fa_icon 'user-plus'
= t('accounts.follow')
- elsif !user_signed_in?
.controls
.remote-follow
- = link_to account_remote_follow_path(account), class: 'icon-button' do
+ = link_to (account.local? ? account_remote_follow_path(account) : "web+mastodon://follow?uri=#{account.uri}"), class: 'icon-button' do
= fa_icon 'user-plus'
= t('accounts.remote_follow')
diff --git a/app/views/accounts/_follow_grid.html.haml b/app/views/accounts/_follow_grid.html.haml
index 10fbfa546..a6d0ee817 100644
--- a/app/views/accounts/_follow_grid.html.haml
+++ b/app/views/accounts/_follow_grid.html.haml
@@ -2,6 +2,6 @@
- if accounts.empty?
= render partial: 'accounts/nothing_here'
- else
- = render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: true
+ = render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: !user_signed_in?
= paginate follows
diff --git a/app/views/remote_unfollows/_card.html.haml b/app/views/remote_unfollows/_card.html.haml
new file mode 100644
index 000000000..e81e292ba
--- /dev/null
+++ b/app/views/remote_unfollows/_card.html.haml
@@ -0,0 +1,13 @@
+.account-card
+ .detailed-status__display-name
+ %div
+ = image_tag account.avatar.url(:original), alt: '', width: 48, height: 48, class: 'avatar'
+
+ %span.display-name
+ - account_url = local_assigns[:admin] ? admin_account_path(account.id) : TagManager.instance.url_for(account)
+ = link_to account_url, class: 'detailed-status__display-name p-author h-card', target: '_blank', rel: 'noopener' do
+ %strong.emojify= display_name(account)
+ %span @#{account.acct}
+
+ - if account.note?
+ .account__header__content.emojify= Formatter.instance.simplified_format(account)
diff --git a/app/views/remote_unfollows/_post_follow_actions.html.haml b/app/views/remote_unfollows/_post_follow_actions.html.haml
new file mode 100644
index 000000000..2a9c062e9
--- /dev/null
+++ b/app/views/remote_unfollows/_post_follow_actions.html.haml
@@ -0,0 +1,4 @@
+.post-follow-actions
+ %div= link_to t('authorize_follow.post_follow.web'), web_url("accounts/#{@account.id}"), class: 'button button--block'
+ %div= link_to t('authorize_follow.post_follow.return'), TagManager.instance.url_for(@account), class: 'button button--block'
+ %div= t('authorize_follow.post_follow.close')
diff --git a/app/views/remote_unfollows/error.html.haml b/app/views/remote_unfollows/error.html.haml
new file mode 100644
index 000000000..cb63f02be
--- /dev/null
+++ b/app/views/remote_unfollows/error.html.haml
@@ -0,0 +1,3 @@
+.form-container
+ .flash-message#error_explanation
+ = t('remote_unfollow.error')
diff --git a/app/views/remote_unfollows/success.html.haml b/app/views/remote_unfollows/success.html.haml
new file mode 100644
index 000000000..aa3c838a0
--- /dev/null
+++ b/app/views/remote_unfollows/success.html.haml
@@ -0,0 +1,10 @@
+- content_for :page_title do
+ = t('remote_unfollow.title', acct: @account.acct)
+
+.form-container
+ .follow-prompt
+ %h2= t('remote_unfollow.unfollowed')
+
+ = render 'card', account: @account
+
+ = render 'post_follow_actions'
diff --git a/config/routes.rb b/config/routes.rb
index 4b5ba5c96..7187fd743 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -116,6 +116,7 @@ Rails.application.routes.draw do
get '/media_proxy/:id/(*any)', to: 'media_proxy#show', as: :media_proxy
# Remote follow
+ resource :remote_unfollow, only: [:create]
resource :authorize_follow, only: [:show, :create]
resource :share, only: [:show, :create]
From cd0eaa349ca5d7e53e2ed246e70e99fc61c98370 Mon Sep 17 00:00:00 2001
From: Levi Bard
Date: Sun, 8 Apr 2018 13:43:10 +0200
Subject: [PATCH 052/442] Enable updating additional account information from
user preferences via rest api (#6789)
* Enable updating additional account information from user preferences via rest api
Resolves #6553
* Pacify rubocop
* Decoerce incoming settings in UserSettingsDecorator
* Create user preferences hash directly from incoming credentials instead of going through ActionController::Parameters
* Clean up user preferences update
* Use ActiveModel::Type::Boolean instead of manually checking stringified number equivalence
---
.../api/v1/accounts/credentials_controller.rb | 12 ++++++++++++
app/lib/user_settings_decorator.rb | 4 ++--
.../api/v1/accounts/credentials_controller_spec.rb | 6 ++++++
spec/lib/user_settings_decorator_spec.rb | 11 +++++++++++
4 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/app/controllers/api/v1/accounts/credentials_controller.rb b/app/controllers/api/v1/accounts/credentials_controller.rb
index 68af22529..062d490a7 100644
--- a/app/controllers/api/v1/accounts/credentials_controller.rb
+++ b/app/controllers/api/v1/accounts/credentials_controller.rb
@@ -13,6 +13,7 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
def update
@account = current_account
UpdateAccountService.new.call(@account, account_params, raise_error: true)
+ UserSettingsDecorator.new(current_user).update(user_settings_params) if user_settings_params
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer
end
@@ -22,4 +23,15 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
def account_params
params.permit(:display_name, :note, :avatar, :header, :locked)
end
+
+ def user_settings_params
+ return nil unless params.key?(:source)
+
+ source_params = params.require(:source)
+
+ {
+ 'setting_default_privacy' => source_params.fetch(:privacy, @account.user.setting_default_privacy),
+ 'setting_default_sensitive' => source_params.fetch(:sensitive, @account.user.setting_default_sensitive),
+ }
+ end
end
diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb
index 4d6f19467..9260a81bc 100644
--- a/app/lib/user_settings_decorator.rb
+++ b/app/lib/user_settings_decorator.rb
@@ -83,7 +83,7 @@ class UserSettingsDecorator
end
def boolean_cast_setting(key)
- settings[key] == '1'
+ ActiveModel::Type::Boolean.new.cast(settings[key])
end
def coerced_settings(key)
@@ -91,7 +91,7 @@ class UserSettingsDecorator
end
def coerce_values(params_hash)
- params_hash.transform_values { |x| x == '1' }
+ params_hash.transform_values { |x| ActiveModel::Type::Boolean.new.cast(x) }
end
def change?(key)
diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
index 461b8b34b..87fce64eb 100644
--- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
+++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb
@@ -28,6 +28,10 @@ describe Api::V1::Accounts::CredentialsController do
note: "Hi!\n\nToot toot!",
avatar: fixture_file_upload('files/avatar.gif', 'image/gif'),
header: fixture_file_upload('files/attachment.jpg', 'image/jpeg'),
+ source: {
+ privacy: 'unlisted',
+ sensitive: true,
+ }
}
end
@@ -42,6 +46,8 @@ describe Api::V1::Accounts::CredentialsController do
expect(user.account.note).to eq("Hi!\n\nToot toot!")
expect(user.account.avatar).to exist
expect(user.account.header).to exist
+ expect(user.setting_default_privacy).to eq('unlisted')
+ expect(user.setting_default_sensitive).to eq(true)
end
it 'queues up an account update distribution' do
diff --git a/spec/lib/user_settings_decorator_spec.rb b/spec/lib/user_settings_decorator_spec.rb
index fee875373..462c5b124 100644
--- a/spec/lib/user_settings_decorator_spec.rb
+++ b/spec/lib/user_settings_decorator_spec.rb
@@ -69,5 +69,16 @@ describe UserSettingsDecorator do
settings.update(values)
expect(user.settings['system_font_ui']).to eq false
end
+
+ it 'decoerces setting values before applying' do
+ values = {
+ 'setting_delete_modal' => 'false',
+ 'setting_boost_modal' => 'true',
+ }
+
+ settings.update(values)
+ expect(user.settings['delete_modal']).to eq false
+ expect(user.settings['boost_modal']).to eq true
+ end
end
end
From c9cbb8de703e321c0d152813a2e22471ffe5eef7 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Sun, 8 Apr 2018 14:26:58 +0200
Subject: [PATCH 053/442] Add search item to tab bar for mobile devices (#7072)
* Add search item to tab bar for mobile devices
* Fix missing prop validation
---
app/javascript/mastodon/features/compose/index.js | 5 +++--
app/javascript/mastodon/features/ui/components/tabs_bar.js | 1 +
app/javascript/mastodon/features/ui/index.js | 2 ++
app/javascript/mastodon/locales/defaultMessages.json | 4 ++++
app/javascript/mastodon/locales/en.json | 1 +
5 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js
index d5cd854db..da5bf7cff 100644
--- a/app/javascript/mastodon/features/compose/index.js
+++ b/app/javascript/mastodon/features/compose/index.js
@@ -38,6 +38,7 @@ export default class Compose extends React.PureComponent {
columns: ImmutablePropTypes.list.isRequired,
multiColumn: PropTypes.bool,
showSearch: PropTypes.bool,
+ isSearchPage: PropTypes.bool,
intl: PropTypes.object.isRequired,
};
@@ -58,7 +59,7 @@ export default class Compose extends React.PureComponent {
}
render () {
- const { multiColumn, showSearch, intl } = this.props;
+ const { multiColumn, showSearch, isSearchPage, intl } = this.props;
let header = '';
@@ -102,7 +103,7 @@ export default class Compose extends React.PureComponent {
)}
-
+
{({ x }) => (
diff --git a/app/javascript/mastodon/features/ui/components/tabs_bar.js b/app/javascript/mastodon/features/ui/components/tabs_bar.js
index dba3be98b..ed6de6f39 100644
--- a/app/javascript/mastodon/features/ui/components/tabs_bar.js
+++ b/app/javascript/mastodon/features/ui/components/tabs_bar.js
@@ -8,6 +8,7 @@ import { isUserTouching } from '../../../is_mobile';
export const links = [
,
,
+ ,
,
,
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 8894eb4e6..8b905fa1d 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -146,6 +146,8 @@ class SwitchingColumnsArea extends React.PureComponent {
+
+
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 5059fc67b..52b9db9ac 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -1717,6 +1717,10 @@
"defaultMessage": "Notifications",
"id": "tabs_bar.notifications"
},
+ {
+ "defaultMessage": "Search",
+ "id": "tabs_bar.search"
+ },
{
"defaultMessage": "Local",
"id": "tabs_bar.local_timeline"
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 23040f7e4..2286d2e83 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -269,6 +269,7 @@
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notifications",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",
From 0893b1669548858daee79ab1260fb98646a0b3fa Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Sun, 8 Apr 2018 18:25:08 +0200
Subject: [PATCH 054/442] Hide search from Compose on mobile devices (#7077)
* Hide search from Compose on mobile devices
We're presently seeing large numbers of users accidentally tooting what they're trying to search for. This PR hides the search form from the Compose view, now that we have a dedicated "search" tab on mobile.
* Don't "showSearch" on mobile if we're not currently searching (isSearchPage)
---
app/javascript/mastodon/features/compose/index.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js
index da5bf7cff..67f0e7981 100644
--- a/app/javascript/mastodon/features/compose/index.js
+++ b/app/javascript/mastodon/features/compose/index.js
@@ -24,9 +24,9 @@ const messages = defineMessages({
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
});
-const mapStateToProps = state => ({
+const mapStateToProps = (state, ownProps) => ({
columns: state.getIn(['settings', 'columns']),
- showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
+ showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : ownProps.isSearchPage,
});
@connect(mapStateToProps)
@@ -90,7 +90,7 @@ export default class Compose extends React.PureComponent {
{header}
-
+ {(multiColumn || isSearchPage) && }
From 498327b2e3f2e64f3a11993afdbd9d87ba73cc92 Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Mon, 9 Apr 2018 16:58:53 +0900
Subject: [PATCH 055/442] Exclude status itself from context query (#7083)
ancestor_statuses and descendant_statuses used to include the root status
itself, but the behavior is confusing because the root status is not
an ancestor nor descendant.
---
app/models/concerns/status_threading_concern.rb | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb
index 65f8e112e..b539ba10e 100644
--- a/app/models/concerns/status_threading_concern.rb
+++ b/app/models/concerns/status_threading_concern.rb
@@ -15,16 +15,12 @@ module StatusThreadingConcern
def ancestor_ids
Rails.cache.fetch("ancestors:#{id}") do
- ancestors_without_self.pluck(:id)
+ ancestor_statuses.pluck(:id)
end
end
- def ancestors_without_self
- ancestor_statuses - [self]
- end
-
def ancestor_statuses
- Status.find_by_sql([<<-SQL.squish, id: id])
+ Status.find_by_sql([<<-SQL.squish, id: in_reply_to_id])
WITH RECURSIVE search_tree(id, in_reply_to_id, path)
AS (
SELECT id, in_reply_to_id, ARRAY[id]
@@ -43,11 +39,7 @@ module StatusThreadingConcern
end
def descendant_ids
- descendants_without_self.pluck(:id)
- end
-
- def descendants_without_self
- descendant_statuses - [self]
+ descendant_statuses.pluck(:id)
end
def descendant_statuses
@@ -56,7 +48,7 @@ module StatusThreadingConcern
AS (
SELECT id, ARRAY[id]
FROM statuses
- WHERE id = :id
+ WHERE in_reply_to_id = :id
UNION ALL
SELECT statuses.id, path || statuses.id
FROM search_tree
From 07d90b0414a68a7864cf824dcd55c4b7b5b9b984 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?=
Date: Mon, 9 Apr 2018 10:28:53 +0200
Subject: [PATCH 056/442] i18n: Update Polish translation (#7085)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marcin Mikołajczak
---
app/javascript/mastodon/locales/pl.json | 1 +
config/locales/pl.yml | 77 +++++++++++++++++++++++++
2 files changed, 78 insertions(+)
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index ff7180df3..041935689 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -269,6 +269,7 @@
"tabs_bar.home": "Strona główna",
"tabs_bar.local_timeline": "Lokalne",
"tabs_bar.notifications": "Powiadomienia",
+ "tabs_bar.search": "Szukaj",
"ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.",
"upload_area.title": "Przeciągnij i upuść aby wysłać",
"upload_button.label": "Dodaj zawartość multimedialną",
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 64c1ff5ea..d303171fb 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -700,6 +700,83 @@ pl:
reblogged: podbił
sensitive_content: Wrażliwa zawartość
terms:
+ body_html: |
+
Polityka prywatności
+
Jakie informacje zbieramy?
+
+
+
Podstawowe informacje o koncie: Podczas rejestracji na tym serwerze, możesz zostać poproszony o wprowadzenie nazwy użytkownika, adresu e-mail i hasła. Możesz także wprowadzić dodatkowe informacje o profilu, takie jak nazwa wyświetlana i biografia oraz wysłać awatar i obraz nagłówka. Nazwa użytkownika, nazwa wyświetlana, biografia, awatar i obraz nagłówka są zawsze widoczne dla wszystkich.
+
Wpisy, śledzenie i inne publiczne informacje: Lista osób które śledzisz jest widoczna publicznie, tak jak lista osób, które Cię śledzą. Jeżeli dodasz wpis, data i czas jego utworzenia i aplikacja, z której go wysłano są przechowywane. Wiadomości mogą zawierać załączniki multimedialne, takie jak zdjęcia i filmy. Publiczne i niewidoczne wpisy są dostępne publicznie. Udostępniony wpis również jest widoczny publicznie. Twoje wpisy są dostarczane obserwującym, co oznacza że jego kopie mogą zostać dostarczone i być przechowywane na innych serwerach. Kiedy usuniesz wpis, przestaje być widoczny również dla osób śledzących Cię. „Podbijanie” i dodanie do ulubionych jest zawsze publiczne.
+
Wpisy bezpośrednie i tylko dla śledzących: Wszystkie wpisy są przechowywane i przetwarzane na serwerze. Wpisy przeznaczone tylko dla śledzących są widoczne tylko dla nich i osób wspomnianych we wpisie, a wpisy bezpośrednie tylko dla wspimnianych. W wielu przypadkach oznacza to, że ich kopie są dostarczane i przechowywane na innych serwerach. Staramy się ograniczać zasięg tych wpisów wyłącznie do właściwych odbiorców, ale inne serwery mogą tego nie robić. Ważne jest, aby sprawdzać jakich serwerów używają osoby, które Cię śledzą. Możesz aktywować opcję pozwalającą na ręczne akceptowanie i odrzucanie nowych śledzących. Pamiętaj, że właściciele serwerów mogą zobaczyć te wiadomości, a odbiorcy mogą wykonać zrzut ekranu, skopiować lub udostępniać ten wpis. Nie udostępniaj wrażliwych danych z użyciem Mastodona.
+
Adresy IP i inne metadane: Kiedy zalogujesz się, przechowujemy adres IP użyty w trakcie logowania wraz z nazwą używanej przeglądarki. Wszystkie aktywne sesje możesz zobaczyć (i wygasić) w ustawieniach. Ostatnio używany adres IP jest przechowywany przez nas do 12 miesięcy. Możemy również przechowywać adresy IP wykorzystywane przy każdym działaniu na serwerze.
+
+
+
+
+
W jakim celu wykorzystujecie informacje?
+
+
Zebrane informacje mogą zostać użyte w następujące sposoby:
+
+
+
Aby dostarczyć podstawową funkcjonalność Mastodona. Możesz wchodzić w interakcje z zawartością tworzoną przez innych tylko gdy jesteś zalogowany. Na przykład, możesz śledzić innych, aby widzieć ich wpisy w dostosowanej osi czasu.
+
Aby wspomóc moderację społeczności, na przykład porównując Twój adres IP ze znanymi, aby rozpoznać próbę obejścia blokady i inne naruszenia.
+
Adres e-mail może zostać wykorzystany, aby wysyłać Ci informacje, powiadomienia o osobach wchodzących w interakcje z tworzoną przez Ciebie zawartością, wysyłających Ci wiadomości, odpowiadać na zgłoszenia i inne żądania lub zapytania.
+
+
+
+
+
W jaki sposób chronimy Twoje dane?
+
+
Wykorzystujemy różne zabezpieczenia, aby zapewnić bezpieczeństwo informacji, które wprowadzasz, wysyłasz lub do których uzyskujesz dostęp. Poza tym, sesja przeglądarki oraz ruch pomiędzy aplikacją a API jest zabezpieczany z użyciem SSL, a hasło jest hashowane z użyciem silnego algorytmu. Możesz też aktywować uwierzytelnianie dwustopniowe, aby lepiej zabezpieczyć dostęp do konta.
+
+
+
+
Jaka jest nasza polityka przechowywania danych?
+
+
Staramy się:
+
+
+
Przechowywać logi zawierające adresy IP używane przy każdym żądaniu do serwera przez nie dłużej niż 90 dni.
+
Przechowywać adresy IP przypisane do użytkowników przez nie dłużej niż 12 miesięcy.
+
+
+
Możesz zażądać i pobrać archiwum tworzonej zawartości, wliczając Twoje wpisy, załączniki multimedialne, awatar i zdjęcie nagłówka.
+
+
Możesz nieodwracalnie usunąć konto w każdej chwili.
+
+
+
+
Czy używany plików cookies?
+
+
Tak. Pliki cookies są małymi plikami, które strona lub dostawca jej usługi dostarcza na dysk twardy komputera z użyciem przeglądarki internetowej (jeżeli na to pozwoli). Pliki cookies pozwalają na rozpoznanie przeglądarki i – jeśli jesteś zarejestrowany – przypisanie jej do konta.
+
+
Wykorzystujemy pliki cookies, aby przechowywać preferencję użytkowników na przyszłe wizyty.
+
+
+
+
Czy przekazujemy informacje osobom trzecim?
+
+
Nie sprzedajemy, nie wymieniamy i nie przekazujemy osobom trzecim informacji pozwalających na identyfikację Ciebie. Nie dotyczy to zaufanym dostawcom pomagającym w prowadzeniu lub obsługiwaniu użytkowników, jeżeli zgadzają się, aby nie przekazywać dalej tych informacji. Możemy również udostępnić informacje, jeżeli uważany to za wymagane przez prawo, konieczne do wypełnienia polityki strony, przestrzegania naszych lub cudzych praw, własności i bezpieczeństwa.
+
+
Twoja publiczna zawartość może zostać pobrana przez inne serwery w sieci. Wpisy publiczne i tylko dla śledzących są dostarczane na serwery, na których znajdują się śledzący Cię, a wiadomości bezpośrednie trafiają na serwery adresatów, jeżeli są oni użytkownikami innego serwera.
+
+
Kiedy pozwolisz aplikacji na dostęp do Twojego konta, w zależności od nadanych jej pozwoleń, może uzyskać dostęp do publicznych informacji, listy śledzonych, Twoich list, wszystkich wpisów i ulubionych. Aplikacje nie mogą uzyskać dostępu do Twojego adresu e-mail i hasła.
Ta strona, produkty i usługi są przeznaczone dla osób, które ukończyły 13 lat. Jeżeli serwer znajduje się w USA, a nie ukończyłeś 13 roku życia, zgodnie z wymogami COPPA (Prawo o Ochronie Prywatności Dzieci w Internecie), nie używaj tej strony.
+
+
+
+
Zmiany w naszej polityce prywatności
+
+
Jeżeli zdecydujemy się na zmiany w polityce prywatności, pojawią się na tej stronie.
+
+
Dokument jest dostępny na licencji CC-BY-SA. Ostatnio zmodyfikowano go 7 marca 2018, przetłumaczono 9 kwietnia 2018. Tłumaczenie (mimo dołożenia wszelkich starań) może nie być w pełni poprawne.
l*J+EN)J@3@I%MSTUxno4>ab^D
zo!hD-?igG8T%!plB({Y4Wb8%Sye+1AHEJhrEDEV4K5vV=NkQS%JQ6y7NQ8Q|QL*Li
zme5qIa$RjHwFiPC$qg*2SguthS(8*vl7;*bjV)^Fp)=5qyAShn^sFt8;yBPSp3P>}
z*>=?rhgeos6-x?MlnPZ;qDwEf<`plxpCwu3>5|9}-5_>-Pe}4weSaFaMKLK<9Qn8=
zK~czya(0v=o?8Kys}f!pYr4Q;Y_L5FgG-RNU?u$-KgOv#mv_fF>S
zhOp#H7M8X`HbXictJVpL6_YOg7_@_$w0A0s(vuomO@2?NeI)6)BwJ2#n!xlOcW}8b
zfuboA%mI|;9JJjXE4H2~3)GhKq=WIpp6`#1Y{?ug`a$S)k|oj<-Z3rP^^zue7Yr>A
z0{I+U8~EYGiVb&S4G9jsp^leMpe&k7>-b|oq{Ae}wvN}iK~&mk+JP6vmS>ZLu0b7D
z*LAeM)MzRF`k>O6`^`#CRhyMoLy{`Cy4@Po`*v;Mko3+?6NcYN-SzEhvRLxe&U2;)
z;Wtu$6uNYyv&KM^-2L;GSd->PseLz!{qPdBEp6U(D?1^du6h?2#%{VL1y&f5WWlw?
z#fmHTuwsi!V$y}HS$49S8Ig5C938LtmN!+z|HX>emZNjCMrAk$s
zlSKX?o>?K;9ny|?wzZMvT@Bn^z#duNkT?cjuv<9FAv#X}FUIcb+-2U?DP1)A%@)v;
zZBV1_LkDA}(F%FPB4?kso_*Y$$oP
zk{d)Ndv&&xoY2P#Vl?XY?YfT3?sCMDJ167Qu1lAElr%CWl7^K1Yvax~!~uUEmrWG-
z`%mXF^U{Y4`dovH2br3({cP92XN26mVRS2Gi!an24Z&Yis$cAo1w?fiwCd;2+IjAJCTw1$+P4MCj^m
zgg*NMp}()`?{5fAC4_!|jF9#fLa+N@KKkh))!sYk?)K)t^#8iP-nmWBudi>TJO8}&
V@6X>(EqaO$_71z>z5n?0{{X8qwp0KB
From 904a2479dd2085dfc94f33746ad6f7a755e72609 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Mon, 9 Apr 2018 17:09:11 +0200
Subject: [PATCH 058/442] Feature: Direct message from Statuses (#7089)
* Fix: Switching between composing direct message and mention from menus
Previously clicking "direct message" followed by "mention" resulted in the composed status staying as "direct", along with weird spacing of items in the text area. This attempts to fix that.
* Fix: Add missing proptype check for onMention in Status component
* Add the ability to send a direct message to a user from the menu on Statuses
* Add space between "Embed" and "Mention" on expanded statuses menu
---
app/javascript/mastodon/components/status.js | 2 ++
.../mastodon/components/status_action_bar.js | 7 +++++++
.../mastodon/containers/status_container.js | 5 +++++
.../features/status/components/action_bar.js | 8 ++++++++
.../mastodon/features/status/index.js | 6 ++++++
.../mastodon/locales/defaultMessages.json | 8 ++++++++
app/javascript/mastodon/locales/en.json | 1 +
app/javascript/mastodon/reducers/compose.js | 20 ++++++++++---------
8 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
index a918a94f8..6129b3f1e 100644
--- a/app/javascript/mastodon/components/status.js
+++ b/app/javascript/mastodon/components/status.js
@@ -31,6 +31,8 @@ export default class Status extends ImmutablePureComponent {
onFavourite: PropTypes.func,
onReblog: PropTypes.func,
onDelete: PropTypes.func,
+ onDirect: PropTypes.func,
+ onMention: PropTypes.func,
onPin: PropTypes.func,
onOpenMedia: PropTypes.func,
onOpenVideo: PropTypes.func,
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
index e036dc1da..10f34b0c7 100644
--- a/app/javascript/mastodon/components/status_action_bar.js
+++ b/app/javascript/mastodon/components/status_action_bar.js
@@ -9,6 +9,7 @@ import { me } from '../initial_state';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
+ direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
block: { id: 'account.block', defaultMessage: 'Block @{name}' },
@@ -41,6 +42,7 @@ export default class StatusActionBar extends ImmutablePureComponent {
onFavourite: PropTypes.func,
onReblog: PropTypes.func,
onDelete: PropTypes.func,
+ onDirect: PropTypes.func,
onMention: PropTypes.func,
onMute: PropTypes.func,
onBlock: PropTypes.func,
@@ -92,6 +94,10 @@ export default class StatusActionBar extends ImmutablePureComponent {
this.props.onMention(this.props.status.get('account'), this.context.router.history);
}
+ handleDirectClick = () => {
+ this.props.onDirect(this.props.status.get('account'), this.context.router.history);
+ }
+
handleMuteClick = () => {
this.props.onMute(this.props.status.get('account'));
}
@@ -149,6 +155,7 @@ export default class StatusActionBar extends ImmutablePureComponent {
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
} else {
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
+ menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
menu.push(null);
menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
diff --git a/app/javascript/mastodon/containers/status_container.js b/app/javascript/mastodon/containers/status_container.js
index 4579bd132..f22509edf 100644
--- a/app/javascript/mastodon/containers/status_container.js
+++ b/app/javascript/mastodon/containers/status_container.js
@@ -5,6 +5,7 @@ import { makeGetStatus } from '../selectors';
import {
replyCompose,
mentionCompose,
+ directCompose,
} from '../actions/compose';
import {
reblog,
@@ -102,6 +103,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
}
},
+ onDirect (account, router) {
+ dispatch(directCompose(account, router));
+ },
+
onMention (account, router) {
dispatch(mentionCompose(account, router));
},
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js
index 13cc10c9c..4aa6b08f2 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.js
+++ b/app/javascript/mastodon/features/status/components/action_bar.js
@@ -8,6 +8,7 @@ import { me } from '../../../initial_state';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
+ direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
reply: { id: 'status.reply', defaultMessage: 'Reply' },
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
@@ -37,6 +38,7 @@ export default class ActionBar extends React.PureComponent {
onReblog: PropTypes.func.isRequired,
onFavourite: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
+ onDirect: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired,
onMute: PropTypes.func,
onMuteConversation: PropTypes.func,
@@ -63,6 +65,10 @@ export default class ActionBar extends React.PureComponent {
this.props.onDelete(this.props.status);
}
+ handleDirectClick = () => {
+ this.props.onDirect(this.props.status.get('account'), this.context.router.history);
+ }
+
handleMentionClick = () => {
this.props.onMention(this.props.status.get('account'), this.context.router.history);
}
@@ -108,6 +114,7 @@ export default class ActionBar extends React.PureComponent {
if (publicStatus) {
menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed });
+ menu.push(null);
}
if (me === status.getIn(['account', 'id'])) {
@@ -121,6 +128,7 @@ export default class ActionBar extends React.PureComponent {
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
} else {
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
+ menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
menu.push(null);
menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index 2f482b292..55eff0823 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -19,6 +19,7 @@ import {
import {
replyCompose,
mentionCompose,
+ directCompose,
} from '../../actions/compose';
import { blockAccount } from '../../actions/accounts';
import {
@@ -148,6 +149,10 @@ export default class Status extends ImmutablePureComponent {
}
}
+ handleDirectClick = (account, router) => {
+ this.props.dispatch(directCompose(account, router));
+ }
+
handleMentionClick = (account, router) => {
this.props.dispatch(mentionCompose(account, router));
}
@@ -379,6 +384,7 @@ export default class Status extends ImmutablePureComponent {
onFavourite={this.handleFavouriteClick}
onReblog={this.handleReblogClick}
onDelete={this.handleDeleteClick}
+ onDirect={this.handleDirectClick}
onMention={this.handleMentionClick}
onMute={this.handleMuteClick}
onMuteConversation={this.handleConversationMuteClick}
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 52b9db9ac..03be288bb 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -197,6 +197,10 @@
"defaultMessage": "Delete",
"id": "status.delete"
},
+ {
+ "defaultMessage": "Direct message @{name}",
+ "id": "status.direct"
+ },
{
"defaultMessage": "Mention @{name}",
"id": "status.mention"
@@ -1370,6 +1374,10 @@
"defaultMessage": "Delete",
"id": "status.delete"
},
+ {
+ "defaultMessage": "Direct message @{name}",
+ "id": "status.direct"
+ },
{
"defaultMessage": "Mention @{name}",
"id": "status.mention"
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 2286d2e83..a389735c1 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Delete",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Favourite",
"status.load_more": "Load more",
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index 1f4177585..87049ea79 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -259,16 +259,18 @@ export default function compose(state = initialState, action) {
case COMPOSE_UPLOAD_PROGRESS:
return state.set('progress', Math.round((action.loaded / action.total) * 100));
case COMPOSE_MENTION:
- return state
- .update('text', text => `${text}@${action.account.get('acct')} `)
- .set('focusDate', new Date())
- .set('idempotencyKey', uuid());
+ return state.withMutations(map => {
+ map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
+ map.set('focusDate', new Date());
+ map.set('idempotencyKey', uuid());
+ });
case COMPOSE_DIRECT:
- return state
- .update('text', text => `@${action.account.get('acct')} `)
- .set('privacy', 'direct')
- .set('focusDate', new Date())
- .set('idempotencyKey', uuid());
+ return state.withMutations(map => {
+ map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
+ map.set('privacy', 'direct');
+ map.set('focusDate', new Date());
+ map.set('idempotencyKey', uuid());
+ });
case COMPOSE_SUGGESTIONS_CLEAR:
return state.update('suggestions', ImmutableList(), list => list.clear()).set('suggestion_token', null);
case COMPOSE_SUGGESTIONS_READY:
From 0c52654b5275fd0e7a0b544d3c6f895825e4a266 Mon Sep 17 00:00:00 2001
From: "Renato \"Lond\" Cerqueira"
Date: Mon, 9 Apr 2018 23:02:42 +0200
Subject: [PATCH 059/442] When creating status, if no sensitive status is
given, use default (#7057)
Clients using the API that do not provide the sensitive flag are always
posting with false sensitive option.
---
app/services/post_status_service.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/services/post_status_service.rb b/app/services/post_status_service.rb
index c91192181..9d2c7a4dc 100644
--- a/app/services/post_status_service.rb
+++ b/app/services/post_status_service.rb
@@ -28,7 +28,7 @@ class PostStatusService < BaseService
status = account.statuses.create!(text: text,
media_attachments: media || [],
thread: in_reply_to,
- sensitive: options[:sensitive],
+ sensitive: (options[:sensitive].nil? ? account.user&.setting_default_sensitive : options[:sensitive]),
spoiler_text: options[:spoiler_text] || '',
visibility: options[:visibility] || account.user&.setting_default_privacy,
language: LanguageDetector.instance.detect(text, account),
From 80a944c882ddbca4d546d03503f0ccff15703484 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 10 Apr 2018 01:20:18 +0200
Subject: [PATCH 060/442] Log rate limit hits (#7096)
Fix #7095
---
config/initializers/rack_attack_logging.rb | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 config/initializers/rack_attack_logging.rb
diff --git a/config/initializers/rack_attack_logging.rb b/config/initializers/rack_attack_logging.rb
new file mode 100644
index 000000000..2ddbfb99c
--- /dev/null
+++ b/config/initializers/rack_attack_logging.rb
@@ -0,0 +1,4 @@
+ActiveSupport::Notifications.subscribe('rack.attack') do |_name, _start, _finish, _request_id, req|
+ next unless [:throttle, :blacklist].include? req.env['rack.attack.match_type']
+ Rails.logger.info("Rate limit hit (#{req.env['rack.attack.match_type']}): #{req.ip} #{req.request_method} #{req.fullpath}")
+end
From e6e93ecd8a45cea5f0c398054c2292a5fdf944cf Mon Sep 17 00:00:00 2001
From: MIYAGI Hikaru
Date: Tue, 10 Apr 2018 16:11:55 +0900
Subject: [PATCH 061/442] Fix GIFV encoding params (#7098)
- Explicitly specify video codec.
When ffmpeg isn't compiled with libx264 but openh264, mpeg4 is selected as video codec.
- Swap avarage bitrate and max bitrate.
---
app/models/media_attachment.rb | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index ac2aa7ed2..8fd9ac09f 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -130,8 +130,9 @@ class MediaAttachment < ApplicationRecord
'pix_fmt' => 'yuv420p',
'vf' => 'scale=\'trunc(iw/2)*2:trunc(ih/2)*2\'',
'vsync' => 'cfr',
- 'b:v' => '1300K',
- 'maxrate' => '500K',
+ 'c:v' => 'h264',
+ 'b:v' => '500K',
+ 'maxrate' => '1300K',
'bufsize' => '1300K',
'crf' => 18,
},
From 219a4423d8371fc89f122f3ef4874e9121b423f7 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Tue, 10 Apr 2018 09:16:06 +0200
Subject: [PATCH 062/442] Feature: Allow staff to change user emails (#7074)
* Admin: Show unconfirmed email address on account page
* Admin: Allow staff to change user email addresses
* ActionLog: On change_email, log current email address and new unconfirmed email address
---
.../admin/change_emails_controller.rb | 49 +++++++++++++++++++
app/helpers/admin/action_logs_helper.rb | 4 +-
app/models/account.rb | 1 +
app/models/admin/action_log.rb | 5 ++
app/policies/user_policy.rb | 4 ++
app/views/admin/accounts/show.html.haml | 6 ++-
app/views/admin/change_emails/show.html.haml | 7 +++
config/locales/en.yml | 9 ++++
config/routes.rb | 1 +
.../admin/change_email_controller_spec.rb | 47 ++++++++++++++++++
10 files changed, 131 insertions(+), 2 deletions(-)
create mode 100644 app/controllers/admin/change_emails_controller.rb
create mode 100644 app/views/admin/change_emails/show.html.haml
create mode 100644 spec/controllers/admin/change_email_controller_spec.rb
diff --git a/app/controllers/admin/change_emails_controller.rb b/app/controllers/admin/change_emails_controller.rb
new file mode 100644
index 000000000..a689d3a53
--- /dev/null
+++ b/app/controllers/admin/change_emails_controller.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Admin
+ class ChangeEmailsController < BaseController
+ before_action :set_account
+ before_action :require_local_account!
+
+ def show
+ authorize @user, :change_email?
+ end
+
+ def update
+ authorize @user, :change_email?
+
+ new_email = resource_params.fetch(:unconfirmed_email)
+
+ if new_email != @user.email
+ @user.update!(
+ unconfirmed_email: new_email,
+ # Regenerate the confirmation token:
+ confirmation_token: nil
+ )
+
+ log_action :change_email, @user
+
+ @user.send_confirmation_instructions
+ end
+
+ redirect_to admin_account_path(@account.id), notice: I18n.t('admin.accounts.change_email.changed_msg')
+ end
+
+ private
+
+ def set_account
+ @account = Account.find(params[:account_id])
+ @user = @account.user
+ end
+
+ def require_local_account!
+ redirect_to admin_account_path(@account.id) unless @account.local? && @account.user.present?
+ end
+
+ def resource_params
+ params.require(:user).permit(
+ :unconfirmed_email
+ )
+ end
+ end
+end
diff --git a/app/helpers/admin/action_logs_helper.rb b/app/helpers/admin/action_logs_helper.rb
index 7c26c0b05..4c663211e 100644
--- a/app/helpers/admin/action_logs_helper.rb
+++ b/app/helpers/admin/action_logs_helper.rb
@@ -45,6 +45,8 @@ module Admin::ActionLogsHelper
log.recorded_changes.slice('domain', 'visible_in_picker')
elsif log.target_type == 'User' && [:promote, :demote].include?(log.action)
log.recorded_changes.slice('moderator', 'admin')
+ elsif log.target_type == 'User' && [:change_email].include?(log.action)
+ log.recorded_changes.slice('email', 'unconfirmed_email')
elsif log.target_type == 'DomainBlock'
log.recorded_changes.slice('severity', 'reject_media')
elsif log.target_type == 'Status' && log.action == :update
@@ -84,7 +86,7 @@ module Admin::ActionLogsHelper
'positive'
when :create
opposite_verbs?(log) ? 'negative' : 'positive'
- when :update, :reset_password, :disable_2fa, :memorialize
+ when :update, :reset_password, :disable_2fa, :memorialize, :change_email
'neutral'
when :demote, :silence, :disable, :suspend, :remove_avatar, :reopen
'negative'
diff --git a/app/models/account.rb b/app/models/account.rb
index 446144a3e..51304fc18 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -124,6 +124,7 @@ class Account < ApplicationRecord
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
delegate :email,
+ :unconfirmed_email,
:current_sign_in_ip,
:current_sign_in_at,
:confirmed?,
diff --git a/app/models/admin/action_log.rb b/app/models/admin/action_log.rb
index c437c8ee8..81f278e07 100644
--- a/app/models/admin/action_log.rb
+++ b/app/models/admin/action_log.rb
@@ -35,6 +35,11 @@ class Admin::ActionLog < ApplicationRecord
self.recorded_changes = target.attributes
when :update, :promote, :demote
self.recorded_changes = target.previous_changes
+ when :change_email
+ self.recorded_changes = ActiveSupport::HashWithIndifferentAccess.new(
+ email: [target.email, nil],
+ unconfirmed_email: [nil, target.unconfirmed_email]
+ )
end
end
end
diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb
index aae207d06..dabdf707a 100644
--- a/app/policies/user_policy.rb
+++ b/app/policies/user_policy.rb
@@ -5,6 +5,10 @@ class UserPolicy < ApplicationPolicy
staff? && !record.staff?
end
+ def change_email?
+ staff? && !record.staff?
+ end
+
def disable_2fa?
admin? && !record.staff?
end
diff --git a/app/views/admin/accounts/show.html.haml b/app/views/admin/accounts/show.html.haml
index fecfd6cc8..7312618ee 100644
--- a/app/views/admin/accounts/show.html.haml
+++ b/app/views/admin/accounts/show.html.haml
@@ -36,9 +36,13 @@
%th= t('admin.accounts.email')
%td
= @account.user_email
-
- if @account.user_confirmed?
= fa_icon('check')
+ = table_link_to 'edit', t('admin.accounts.change_email.label'), admin_account_change_email_path(@account.id) if can?(:change_email, @account.user)
+ - if @account.user_unconfirmed_email.present?
+ %th= t('admin.accounts.unconfirmed_email')
+ %td
+ = @account.user_unconfirmed_email
%tr
%th= t('admin.accounts.login_status')
%td
diff --git a/app/views/admin/change_emails/show.html.haml b/app/views/admin/change_emails/show.html.haml
new file mode 100644
index 000000000..a661b1ad6
--- /dev/null
+++ b/app/views/admin/change_emails/show.html.haml
@@ -0,0 +1,7 @@
+- content_for :page_title do
+ = t('admin.accounts.change_email.title', username: @account.acct)
+
+= simple_form_for @user, url: admin_account_change_email_path(@account.id) do |f|
+ = f.input :email, wrapper: :with_label, disabled: true, label: t('admin.accounts.change_email.current_email')
+ = f.input :unconfirmed_email, wrapper: :with_label, label: t('admin.accounts.change_email.new_email')
+ = f.button :submit, class: "button", value: t('admin.accounts.change_email.submit')
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 70af9530c..11f3fb924 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -63,6 +63,13 @@ en:
are_you_sure: Are you sure?
avatar: Avatar
by_domain: Domain
+ change_email:
+ changed_msg: Account email successfully changed!
+ current_email: Current Email
+ label: Change Email
+ new_email: New Email
+ submit: Change Email
+ title: Change Email for %{username}
confirm: Confirm
confirmed: Confirmed
demote: Demote
@@ -131,6 +138,7 @@ en:
statuses: Statuses
subscribe: Subscribe
title: Accounts
+ unconfirmed_email: Unconfirmed E-mail
undo_silenced: Undo silence
undo_suspension: Undo suspension
unsubscribe: Unsubscribe
@@ -139,6 +147,7 @@ en:
action_logs:
actions:
assigned_to_self_report: "%{name} assigned report %{target} to themselves"
+ change_email_user: "%{name} changed the e-mail address of user %{target}"
confirm_user: "%{name} confirmed e-mail address of user %{target}"
create_custom_emoji: "%{name} uploaded new emoji %{target}"
create_domain_block: "%{name} blocked domain %{target}"
diff --git a/config/routes.rb b/config/routes.rb
index 7187fd743..2776898ac 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -151,6 +151,7 @@ Rails.application.routes.draw do
post :memorialize
end
+ resource :change_email, only: [:show, :update]
resource :reset, only: [:create]
resource :silence, only: [:create, :destroy]
resource :suspension, only: [:create, :destroy]
diff --git a/spec/controllers/admin/change_email_controller_spec.rb b/spec/controllers/admin/change_email_controller_spec.rb
new file mode 100644
index 000000000..50f94f835
--- /dev/null
+++ b/spec/controllers/admin/change_email_controller_spec.rb
@@ -0,0 +1,47 @@
+require 'rails_helper'
+
+RSpec.describe Admin::ChangeEmailsController, type: :controller do
+ render_views
+
+ let(:admin) { Fabricate(:user, admin: true) }
+
+ before do
+ sign_in admin
+ end
+
+ describe "GET #show" do
+ it "returns http success" do
+ account = Fabricate(:account)
+ user = Fabricate(:user, account: account)
+
+ get :show, params: { account_id: account.id }
+
+ expect(response).to have_http_status(:success)
+ end
+ end
+
+ describe "GET #update" do
+ before do
+ allow(UserMailer).to receive(:confirmation_instructions).and_return(double('email', deliver_later: nil))
+ end
+
+ it "returns http success" do
+ account = Fabricate(:account)
+ user = Fabricate(:user, account: account)
+
+ previous_email = user.email
+
+ post :update, params: { account_id: account.id, user: { unconfirmed_email: 'test@example.com' } }
+
+ user.reload
+
+ expect(user.email).to eq previous_email
+ expect(user.unconfirmed_email).to eq 'test@example.com'
+ expect(user.confirmation_token).not_to be_nil
+
+ expect(UserMailer).to have_received(:confirmation_instructions).with(user, user.confirmation_token, { to: 'test@example.com' })
+
+ expect(response).to redirect_to(admin_account_path(account.id))
+ end
+ end
+end
From 8f800ad6917e5fb41d17098f3f860d0d1aedcabe Mon Sep 17 00:00:00 2001
From: Paul Woolcock
Date: Tue, 10 Apr 2018 09:46:27 -0400
Subject: [PATCH 063/442] Change custom emoji search to `ILIKE` instead of `=`
(#7099)
---
app/models/custom_emoji.rb | 4 ++++
app/models/custom_emoji_filter.rb | 2 +-
spec/models/custom_emoji_spec.rb | 24 ++++++++++++++++++++++++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 476178e86..1ec21d1a0 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -58,5 +58,9 @@ class CustomEmoji < ApplicationRecord
where(shortcode: shortcodes, domain: domain, disabled: false)
end
+
+ def search(shortcode)
+ where('"custom_emojis"."shortcode" ILIKE ?', "%#{shortcode}%")
+ end
end
end
diff --git a/app/models/custom_emoji_filter.rb b/app/models/custom_emoji_filter.rb
index 2c09ed65c..c4bc310bb 100644
--- a/app/models/custom_emoji_filter.rb
+++ b/app/models/custom_emoji_filter.rb
@@ -28,7 +28,7 @@ class CustomEmojiFilter
when 'by_domain'
CustomEmoji.where(domain: value)
when 'shortcode'
- CustomEmoji.where(shortcode: value)
+ CustomEmoji.search(value)
else
raise "Unknown filter: #{key}"
end
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
index bb150b837..87367df50 100644
--- a/spec/models/custom_emoji_spec.rb
+++ b/spec/models/custom_emoji_spec.rb
@@ -1,6 +1,30 @@
require 'rails_helper'
RSpec.describe CustomEmoji, type: :model do
+ describe '#search' do
+ let(:custom_emoji) { Fabricate(:custom_emoji, shortcode: shortcode) }
+
+ subject { described_class.search(search_term) }
+
+ context 'shortcode is exact' do
+ let(:shortcode) { 'blobpats' }
+ let(:search_term) { 'blobpats' }
+
+ it 'finds emoji' do
+ is_expected.to include(custom_emoji)
+ end
+ end
+
+ context 'shortcode is partial' do
+ let(:shortcode) { 'blobpats' }
+ let(:search_term) { 'blob' }
+
+ it 'finds emoji' do
+ is_expected.to include(custom_emoji)
+ end
+ end
+ end
+
describe '#local?' do
let(:custom_emoji) { Fabricate(:custom_emoji, domain: domain) }
From 49bbef1202f483d4e8abc43d00d12551bb25f80f Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 10 Apr 2018 16:08:28 +0200
Subject: [PATCH 064/442] Use RAILS_LOG_LEVEL to set log level of Sidekiq, too
(#7079)
Fix #3565 (oops)
---
config/initializers/sidekiq.rb | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index f875fbd95..05c804100 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-namespace = ENV.fetch('REDIS_NAMESPACE') { nil }
+namespace = ENV.fetch('REDIS_NAMESPACE') { nil }
redis_params = { url: ENV['REDIS_URL'] }
if namespace
- redis_params [:namespace] = namespace
+ redis_params[:namespace] = namespace
end
Sidekiq.configure_server do |config|
@@ -18,3 +18,5 @@ end
Sidekiq.configure_client do |config|
config.redis = redis_params
end
+
+Sidekiq::Logging.logger.level = ::Logger::const_get(ENV.fetch('RAILS_LOG_LEVEL', 'info').upcase.to_s)
From 45c9f16f714dd6de15391b5e2ae2bf0d30ef20fb Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 10 Apr 2018 17:12:10 +0200
Subject: [PATCH 065/442] Improve load gap styling in web UI (#7100)
---
.../mastodon/components/load_gap.js | 33 +++++++++++++++++++
.../mastodon/components/status_list.js | 20 +----------
.../mastodon/features/notifications/index.js | 20 +----------
.../styles/mastodon/components.scss | 4 +++
4 files changed, 39 insertions(+), 38 deletions(-)
create mode 100644 app/javascript/mastodon/components/load_gap.js
diff --git a/app/javascript/mastodon/components/load_gap.js b/app/javascript/mastodon/components/load_gap.js
new file mode 100644
index 000000000..012303ae1
--- /dev/null
+++ b/app/javascript/mastodon/components/load_gap.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { injectIntl, defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
+});
+
+@injectIntl
+export default class LoadGap extends React.PureComponent {
+
+ static propTypes = {
+ disabled: PropTypes.bool,
+ maxId: PropTypes.string,
+ onClick: PropTypes.func.isRequired,
+ intl: PropTypes.object.isRequired,
+ };
+
+ handleClick = () => {
+ this.props.onClick(this.props.maxId);
+ }
+
+ render () {
+ const { disabled, intl } = this.props;
+
+ return (
+
+ );
+ }
+
+}
diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js
index 8c2673f30..c98d4564e 100644
--- a/app/javascript/mastodon/components/status_list.js
+++ b/app/javascript/mastodon/components/status_list.js
@@ -4,28 +4,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import StatusContainer from '../containers/status_container';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import LoadMore from './load_more';
+import LoadGap from './load_gap';
import ScrollableList from './scrollable_list';
import { FormattedMessage } from 'react-intl';
-class LoadGap extends ImmutablePureComponent {
-
- static propTypes = {
- disabled: PropTypes.bool,
- maxId: PropTypes.string,
- onClick: PropTypes.func.isRequired,
- };
-
- handleClick = () => {
- this.props.onClick(this.props.maxId);
- }
-
- render () {
- return ;
- }
-
-}
-
export default class StatusList extends ImmutablePureComponent {
static propTypes = {
diff --git a/app/javascript/mastodon/features/notifications/index.js b/app/javascript/mastodon/features/notifications/index.js
index 9a6fb45c8..94a46b833 100644
--- a/app/javascript/mastodon/features/notifications/index.js
+++ b/app/javascript/mastodon/features/notifications/index.js
@@ -13,7 +13,7 @@ import { createSelector } from 'reselect';
import { List as ImmutableList } from 'immutable';
import { debounce } from 'lodash';
import ScrollableList from '../../components/scrollable_list';
-import LoadMore from '../../components/load_more';
+import LoadGap from '../../components/load_gap';
const messages = defineMessages({
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
@@ -24,24 +24,6 @@ const getNotifications = createSelector([
state => state.getIn(['notifications', 'items']),
], (excludedTypes, notifications) => notifications.filterNot(item => item !== null && excludedTypes.includes(item.get('type'))));
-class LoadGap extends React.PureComponent {
-
- static propTypes = {
- disabled: PropTypes.bool,
- maxId: PropTypes.string,
- onClick: PropTypes.func.isRequired,
- };
-
- handleClick = () => {
- this.props.onClick(this.props.maxId);
- }
-
- render () {
- return ;
- }
-
-}
-
const mapStateToProps = state => ({
notifications: getNotifications(state),
isLoading: state.getIn(['notifications', 'isLoading'], true),
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index d76dc10f1..888a0ad82 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -2455,6 +2455,10 @@ a.status-card {
}
}
+.load-gap {
+ border-bottom: 1px solid lighten($ui-base-color, 8%);
+}
+
.regeneration-indicator {
text-align: center;
font-size: 16px;
From d9b62e34da0c0238176f27557ac7b953da94df7e Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Tue, 10 Apr 2018 20:27:59 +0200
Subject: [PATCH 066/442] Feature: Improve reports ui (#7032)
* Further improvements to Reports UI
- Clean up notes display
- Clean up add new note form
- Simplify controller
- Allow reopening a report with a note
- Show created at date for reports
- Fix report details table formatting
* Show history of report using Admin::ActionLog beneath the report
* Fix incorrect log message when reopening a report
* Implement fetching of all ActionLog items that could be related to the report
* Ensure adding a report_note updates the report's updated_at
* Limit Report History to actions that happened between the report being created and the report being resolved
* Fix linting issues
* Improve report history builder
Thanks @gargron for the improvements
---
.../admin/report_notes_controller.rb | 17 +++++--
app/controllers/admin/reports_controller.rb | 20 ++++----
app/javascript/styles/mastodon/admin.scss | 35 ++++++++++++++
app/models/report.rb | 46 ++++++++++++++++++
app/models/report_note.rb | 2 +-
.../admin/report_notes/_report_note.html.haml | 12 ++---
app/views/admin/reports/show.html.haml | 47 ++++++++++++-------
config/locales/en.yml | 11 +++--
8 files changed, 147 insertions(+), 43 deletions(-)
diff --git a/app/controllers/admin/report_notes_controller.rb b/app/controllers/admin/report_notes_controller.rb
index ef8c0f469..bcb3f2026 100644
--- a/app/controllers/admin/report_notes_controller.rb
+++ b/app/controllers/admin/report_notes_controller.rb
@@ -8,19 +8,26 @@ module Admin
authorize ReportNote, :create?
@report_note = current_account.report_notes.new(resource_params)
+ @report = @report_note.report
if @report_note.save
if params[:create_and_resolve]
- @report_note.report.update!(action_taken: true, action_taken_by_account_id: current_account.id)
- log_action :resolve, @report_note.report
+ @report.resolve!(current_account)
+ log_action :resolve, @report
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
- else
- redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.created_msg')
+ return
end
+
+ if params[:create_and_unresolve]
+ @report.unresolve!
+ log_action :reopen, @report
+ end
+
+ redirect_to admin_report_path(@report), notice: I18n.t('admin.report_notes.created_msg')
else
- @report = @report_note.report
@report_notes = @report.notes.latest
+ @report_history = @report.history
@form = Form::StatusBatch.new
render template: 'admin/reports/show'
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index fc3785e3b..a4ae9507d 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -13,6 +13,7 @@ module Admin
authorize @report, :show?
@report_note = @report.notes.new
@report_notes = @report.notes.latest
+ @report_history = @report.history
@form = Form::StatusBatch.new
end
@@ -38,36 +39,33 @@ module Admin
@report.update!(assigned_account_id: nil)
log_action :unassigned, @report
when 'reopen'
- @report.update!(action_taken: false, action_taken_by_account_id: nil)
+ @report.unresolve!
log_action :reopen, @report
when 'resolve'
- @report.update!(action_taken_by_current_attributes)
+ @report.resolve!(current_account)
log_action :resolve, @report
when 'suspend'
Admin::SuspensionWorker.perform_async(@report.target_account.id)
+
log_action :resolve, @report
log_action :suspend, @report.target_account
+
resolve_all_target_account_reports
- @report.reload
when 'silence'
@report.target_account.update!(silenced: true)
+
log_action :resolve, @report
log_action :silence, @report.target_account
+
resolve_all_target_account_reports
- @report.reload
else
raise ActiveRecord::RecordNotFound
end
- end
-
- def action_taken_by_current_attributes
- { action_taken: true, action_taken_by_account_id: current_account.id }
+ @report.reload
end
def resolve_all_target_account_reports
- unresolved_reports_for_target_account.update_all(
- action_taken_by_current_attributes
- )
+ unresolved_reports_for_target_account.update_all(action_taken: true, action_taken_by_account_id: current_account.id)
end
def unresolved_reports_for_target_account
diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss
index e6bd0c717..6bd659030 100644
--- a/app/javascript/styles/mastodon/admin.scss
+++ b/app/javascript/styles/mastodon/admin.scss
@@ -145,6 +145,11 @@
border: 0;
background: transparent;
border-bottom: 1px solid $ui-base-color;
+
+ &.section-break {
+ margin: 30px 0;
+ border-bottom: 2px solid $ui-base-lighter-color;
+ }
}
.muted-hint {
@@ -330,6 +335,36 @@
}
}
+.report-note__comment {
+ margin-bottom: 20px;
+}
+
+.report-note__form {
+ margin-bottom: 20px;
+
+ .report-note__textarea {
+ box-sizing: border-box;
+ border: 0;
+ padding: 7px 4px;
+ margin-bottom: 10px;
+ font-size: 16px;
+ color: $ui-base-color;
+ display: block;
+ width: 100%;
+ outline: 0;
+ font-family: inherit;
+ resize: vertical;
+ }
+
+ .report-note__buttons {
+ text-align: right;
+ }
+
+ .report-note__button {
+ margin: 0 0 5px 5px;
+ }
+}
+
.batch-form-box {
display: flex;
flex-wrap: wrap;
diff --git a/app/models/report.rb b/app/models/report.rb
index f5b37cb6d..5b90c7bce 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -39,4 +39,50 @@ class Report < ApplicationRecord
def media_attachments
MediaAttachment.where(status_id: status_ids)
end
+
+ def assign_to_self!(current_account)
+ update!(assigned_account_id: current_account.id)
+ end
+
+ def unassign!
+ update!(assigned_account_id: nil)
+ end
+
+ def resolve!(acting_account)
+ update!(action_taken: true, action_taken_by_account_id: acting_account.id)
+ end
+
+ def unresolve!
+ update!(action_taken: false, action_taken_by_account_id: nil)
+ end
+
+ def unresolved?
+ !action_taken?
+ end
+
+ def history
+ time_range = created_at..updated_at
+
+ sql = [
+ Admin::ActionLog.where(
+ target_type: 'Report',
+ target_id: id,
+ created_at: time_range
+ ).unscope(:order),
+
+ Admin::ActionLog.where(
+ target_type: 'Account',
+ target_id: target_account_id,
+ created_at: time_range
+ ).unscope(:order),
+
+ Admin::ActionLog.where(
+ target_type: 'Status',
+ target_id: status_ids,
+ created_at: time_range
+ ).unscope(:order),
+ ].map { |query| "(#{query.to_sql})" }.join(' UNION ALL ')
+
+ Admin::ActionLog.from("(#{sql}) AS admin_action_logs")
+ end
end
diff --git a/app/models/report_note.rb b/app/models/report_note.rb
index 3d12cf7b6..6d9dec80a 100644
--- a/app/models/report_note.rb
+++ b/app/models/report_note.rb
@@ -13,7 +13,7 @@
class ReportNote < ApplicationRecord
belongs_to :account
- belongs_to :report, inverse_of: :notes
+ belongs_to :report, inverse_of: :notes, touch: true
scope :latest, -> { reorder('created_at ASC') }
diff --git a/app/views/admin/report_notes/_report_note.html.haml b/app/views/admin/report_notes/_report_note.html.haml
index 60ac5d0d5..1f621e0d3 100644
--- a/app/views/admin/report_notes/_report_note.html.haml
+++ b/app/views/admin/report_notes/_report_note.html.haml
@@ -1,11 +1,9 @@
-%tr
- %td
- %p
- %strong= report_note.account.acct
- on
+%li
+ %h4
+ = report_note.account.acct
+ %div{ style: 'float: right' }
%time.formatted{ datetime: report_note.created_at.iso8601, title: l(report_note.created_at) }
= l report_note.created_at
= table_link_to 'trash', t('admin.reports.notes.delete'), admin_report_note_path(report_note), method: :delete if can?(:destroy, report_note)
- %br/
- %br/
+ %div{ class: 'report-note__comment' }
= simple_format(h(report_note.content))
diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml
index e7634a034..d57b4adc8 100644
--- a/app/views/admin/reports/show.html.haml
+++ b/app/views/admin/reports/show.html.haml
@@ -5,7 +5,7 @@
= t('admin.reports.report', id: @report.id)
%div{ style: 'overflow: hidden; margin-bottom: 20px' }
- - if !@report.action_taken?
+ - if @report.unresolved?
%div{ style: 'float: right' }
= link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
= link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
@@ -17,22 +17,29 @@
.table-wrapper
%table.table.inline-table
%tbody
+ %tr
+ %th= t('admin.reports.created_at')
+ %td{colspan: 2}
+ %time.formatted{ datetime: @report.created_at.iso8601 }
%tr
%th= t('admin.reports.updated_at')
%td{colspan: 2}
%time.formatted{ datetime: @report.updated_at.iso8601 }
%tr
%th= t('admin.reports.status')
- %td{colspan: 2}
+ %td
- if @report.action_taken?
= t('admin.reports.resolved')
- = table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
- else
= t('admin.reports.unresolved')
+ %td{style: "text-align: right; overflow: hidden;"}
+ - if @report.action_taken?
+ = table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
- if !@report.action_taken_by_account.nil?
%tr
%th= t('admin.reports.action_taken_by')
- %td= @report.action_taken_by_account.acct
+ %td{colspan: 2}
+ = @report.action_taken_by_account.acct
- else
%tr
%th= t('admin.reports.assigned')
@@ -47,6 +54,8 @@
- if !@report.assigned_account.nil?
= table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put
+%hr{ class: "section-break"}/
+
.report-accounts
.report-accounts__item
%h3= t('admin.reports.reported_account')
@@ -88,22 +97,28 @@
= link_to admin_report_reported_status_path(@report, status), method: :delete, class: 'icon-button trash-button', title: t('admin.reports.delete'), data: { confirm: t('admin.reports.are_you_sure') }, remote: true do
= fa_icon 'trash'
-%hr/
+%hr{ class: "section-break"}/
%h3= t('admin.reports.notes.label')
- if @report_notes.length > 0
- .table-wrapper
- %table.table
- %thead
- %tr
- %th
- %tbody
- = render @report_notes
+ %ul
+ = render @report_notes
-= simple_form_for @report_note, url: admin_report_notes_path do |f|
+%h4= t('admin.reports.notes.new_label')
+= form_for @report_note, url: admin_report_notes_path, html: { class: 'report-note__form' } do |f|
= render 'shared/error_messages', object: @report_note
- = f.input :content
+ = f.text_area :content, placeholder: t('admin.reports.notes.placeholder'), rows: 6, class: 'report-note__textarea'
= f.hidden_field :report_id
- = f.button :button, t('admin.reports.notes.create'), type: :submit
- = f.button :button, t('admin.reports.notes.create_and_resolve'), type: :submit, name: :create_and_resolve
+ %div{ class: 'report-note__buttons' }
+ - if @report.unresolved?
+ = f.submit t('admin.reports.notes.create_and_resolve'), name: :create_and_resolve, class: 'button report-note__button'
+ - else
+ = f.submit t('admin.reports.notes.create_and_unresolve'), name: :create_and_unresolve, class: 'button report-note__button'
+ = f.submit t('admin.reports.notes.create'), class: 'button report-note__button'
+
+- if @report_history.length > 0
+ %h3= t('admin.reports.history')
+
+ %ul
+ = render @report_history
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 11f3fb924..98f135966 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -256,8 +256,8 @@ en:
title: Filter
title: Invites
report_notes:
- created_msg: Moderation note successfully created!
- destroyed_msg: Moderation note successfully destroyed!
+ created_msg: Report note successfully created!
+ destroyed_msg: Report note successfully deleted!
reports:
action_taken_by: Action taken by
are_you_sure: Are you sure?
@@ -266,15 +266,20 @@ en:
comment:
label: Report Comment
none: None
+ created_at: Reported
delete: Delete
+ history: Moderation History
id: ID
mark_as_resolved: Mark as resolved
mark_as_unresolved: Mark as unresolved
notes:
create: Add Note
create_and_resolve: Resolve with Note
+ create_and_unresolve: Reopen with Note
delete: Delete
- label: Notes
+ label: Moderator Notes
+ new_label: Add Moderator Note
+ placeholder: Describe what actions have been taken, or any other updates to this report…
nsfw:
'false': Unhide media attachments
'true': Hide media attachments
From 519119f657cf97ec187008a28dba00c1125a9292 Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Wed, 11 Apr 2018 19:35:09 +0900
Subject: [PATCH 067/442] Paginate ancestor statuses in public page (#7102)
This also limits the statuses returned by API, but pagination is not
implemented in Web API yet. I still expect it brings user experience
better than making a user wait to fetch all ancestor statuses and flooding
the column with them.
---
app/controllers/api/v1/statuses_controller.rb | 2 +-
app/controllers/statuses_controller.rb | 7 +++-
.../styles/mastodon/stream_entries.scss | 14 ++++++-
.../concerns/status_threading_concern.rb | 24 ++++++++----
app/views/stream_entries/_status.html.haml | 4 ++
.../concerns/status_threading_concern_spec.rb | 38 +++++++++++++++----
.../stream_entries/show.html.haml_spec.rb | 2 +-
7 files changed, 70 insertions(+), 21 deletions(-)
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index 28c28592a..e98241323 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -17,7 +17,7 @@ class Api::V1::StatusesController < Api::BaseController
end
def context
- ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(current_account)
+ ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(DEFAULT_STATUSES_LIMIT, current_account)
descendants_results = @status.descendants(current_account)
loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = cache_collection(descendants_results, Status)
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index 45226c8d2..41f098a43 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -4,6 +4,8 @@ class StatusesController < ApplicationController
include SignatureAuthentication
include Authorization
+ ANCESTORS_LIMIT = 20
+
layout 'public'
before_action :set_account
@@ -16,8 +18,9 @@ class StatusesController < ApplicationController
def show
respond_to do |format|
format.html do
- @ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
- @descendants = cache_collection(@status.descendants(current_account), Status)
+ @ancestors = @status.reply? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT, current_account), Status) : []
+ @next_ancestor = @ancestors.size < ANCESTORS_LIMIT ? nil : @ancestors.shift
+ @descendants = cache_collection(@status.descendants(current_account), Status)
render 'stream_entries/show'
end
diff --git a/app/javascript/styles/mastodon/stream_entries.scss b/app/javascript/styles/mastodon/stream_entries.scss
index 442b143a0..dfdc48d06 100644
--- a/app/javascript/styles/mastodon/stream_entries.scss
+++ b/app/javascript/styles/mastodon/stream_entries.scss
@@ -6,7 +6,8 @@
background: $simple-background-color;
.detailed-status.light,
- .status.light {
+ .status.light,
+ .more.light {
border-bottom: 1px solid $ui-secondary-color;
animation: none;
}
@@ -290,6 +291,17 @@
text-decoration: underline;
}
}
+
+ .more {
+ color: $classic-primary-color;
+ display: block;
+ padding: 14px;
+ text-align: center;
+
+ &:not(:hover) {
+ text-decoration: none;
+ }
+ }
}
.embed {
diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb
index b539ba10e..fffc095ee 100644
--- a/app/models/concerns/status_threading_concern.rb
+++ b/app/models/concerns/status_threading_concern.rb
@@ -3,8 +3,8 @@
module StatusThreadingConcern
extend ActiveSupport::Concern
- def ancestors(account = nil)
- find_statuses_from_tree_path(ancestor_ids, account)
+ def ancestors(limit, account = nil)
+ find_statuses_from_tree_path(ancestor_ids(limit), account)
end
def descendants(account = nil)
@@ -13,14 +13,21 @@ module StatusThreadingConcern
private
- def ancestor_ids
- Rails.cache.fetch("ancestors:#{id}") do
- ancestor_statuses.pluck(:id)
+ def ancestor_ids(limit)
+ key = "ancestors:#{id}"
+ ancestors = Rails.cache.fetch(key)
+
+ if ancestors.nil? || ancestors[:limit] < limit
+ ids = ancestor_statuses(limit).pluck(:id).reverse!
+ Rails.cache.write key, limit: limit, ids: ids
+ ids
+ else
+ ancestors[:ids].last(limit)
end
end
- def ancestor_statuses
- Status.find_by_sql([<<-SQL.squish, id: in_reply_to_id])
+ def ancestor_statuses(limit)
+ Status.find_by_sql([<<-SQL.squish, id: in_reply_to_id, limit: limit])
WITH RECURSIVE search_tree(id, in_reply_to_id, path)
AS (
SELECT id, in_reply_to_id, ARRAY[id]
@@ -34,7 +41,8 @@ module StatusThreadingConcern
)
SELECT id
FROM search_tree
- ORDER BY path DESC
+ ORDER BY path
+ LIMIT :limit
SQL
end
diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml
index e2e1fdd12..2d0dafcb7 100644
--- a/app/views/stream_entries/_status.html.haml
+++ b/app/views/stream_entries/_status.html.haml
@@ -14,6 +14,10 @@
entry_classes = h_class + ' ' + mf_classes + ' ' + style_classes
- if status.reply? && include_threads
+ - if @next_ancestor
+ .entry{ class: entry_classes }
+ = link_to short_account_status_url(@next_ancestor.account.username, @next_ancestor), class: 'more light' do
+ = t('statuses.show_more')
= render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }
.entry{ class: entry_classes }
diff --git a/spec/models/concerns/status_threading_concern_spec.rb b/spec/models/concerns/status_threading_concern_spec.rb
index 62f5f6e31..b8ebdd58c 100644
--- a/spec/models/concerns/status_threading_concern_spec.rb
+++ b/spec/models/concerns/status_threading_concern_spec.rb
@@ -14,34 +14,34 @@ describe StatusThreadingConcern do
let!(:viewer) { Fabricate(:account, username: 'viewer') }
it 'returns conversation history' do
- expect(reply3.ancestors).to include(status, reply1, reply2)
+ expect(reply3.ancestors(4)).to include(status, reply1, reply2)
end
it 'does not return conversation history user is not allowed to see' do
reply1.update(visibility: :private)
status.update(visibility: :direct)
- expect(reply3.ancestors(viewer)).to_not include(reply1, status)
+ expect(reply3.ancestors(4, viewer)).to_not include(reply1, status)
end
it 'does not return conversation history from blocked users' do
viewer.block!(jeff)
- expect(reply3.ancestors(viewer)).to_not include(reply1)
+ expect(reply3.ancestors(4, viewer)).to_not include(reply1)
end
it 'does not return conversation history from muted users' do
viewer.mute!(jeff)
- expect(reply3.ancestors(viewer)).to_not include(reply1)
+ expect(reply3.ancestors(4, viewer)).to_not include(reply1)
end
it 'does not return conversation history from silenced and not followed users' do
jeff.update(silenced: true)
- expect(reply3.ancestors(viewer)).to_not include(reply1)
+ expect(reply3.ancestors(4, viewer)).to_not include(reply1)
end
it 'does not return conversation history from blocked domains' do
viewer.block_domain!('example.com')
- expect(reply3.ancestors(viewer)).to_not include(reply2)
+ expect(reply3.ancestors(4, viewer)).to_not include(reply2)
end
it 'ignores deleted records' do
@@ -49,10 +49,32 @@ describe StatusThreadingConcern do
second_status = Fabricate(:status, thread: first_status, account: alice)
# Create cache and delete cached record
- second_status.ancestors
+ second_status.ancestors(4)
first_status.destroy
- expect(second_status.ancestors).to eq([])
+ expect(second_status.ancestors(4)).to eq([])
+ end
+
+ it 'can return more records than previously requested' do
+ first_status = Fabricate(:status, account: bob)
+ second_status = Fabricate(:status, thread: first_status, account: alice)
+ third_status = Fabricate(:status, thread: second_status, account: alice)
+
+ # Create cache
+ second_status.ancestors(1)
+
+ expect(third_status.ancestors(2)).to eq([first_status, second_status])
+ end
+
+ it 'can return fewer records than previously requested' do
+ first_status = Fabricate(:status, account: bob)
+ second_status = Fabricate(:status, thread: first_status, account: alice)
+ third_status = Fabricate(:status, thread: second_status, account: alice)
+
+ # Create cache
+ second_status.ancestors(2)
+
+ expect(third_status.ancestors(1)).to eq([second_status])
end
end
diff --git a/spec/views/stream_entries/show.html.haml_spec.rb b/spec/views/stream_entries/show.html.haml_spec.rb
index 59ea40990..6074bbc2e 100644
--- a/spec/views/stream_entries/show.html.haml_spec.rb
+++ b/spec/views/stream_entries/show.html.haml_spec.rb
@@ -48,7 +48,7 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
assign(:stream_entry, reply.stream_entry)
assign(:account, alice)
assign(:type, reply.stream_entry.activity_type.downcase)
- assign(:ancestors, reply.stream_entry.activity.ancestors(bob) )
+ assign(:ancestors, reply.stream_entry.activity.ancestors(1, bob) )
assign(:descendants, reply.stream_entry.activity.descendants(bob))
render
From 12f5f13fab1023c3cb2a50c7bcb11f281c7984fb Mon Sep 17 00:00:00 2001
From: ThibG
Date: Wed, 11 Apr 2018 20:42:50 +0200
Subject: [PATCH 068/442] Place privacy dropdown menu top if it is closer to
the bottom of the viewport (#7106)
---
.../compose/components/privacy_dropdown.js | 22 ++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
index e5de13178..6b22ba84a 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
@@ -32,6 +32,10 @@ class PrivacyDropdownMenu extends React.PureComponent {
onChange: PropTypes.func.isRequired,
};
+ state = {
+ mounted: false,
+ };
+
handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) {
this.props.onClose();
@@ -54,6 +58,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
+ this.setState({ mounted: true });
}
componentWillUnmount () {
@@ -66,12 +71,16 @@ class PrivacyDropdownMenu extends React.PureComponent {
}
render () {
+ const { mounted } = this.state;
const { style, items, value } = this.props;
return (
{({ opacity, scaleX, scaleY }) => (
-
+ // It should not be transformed when mounting because the resulting
+ // size will be used to determine the coordinate of the menu by
+ // react-overlays
+
+ )}
+
{info}
{mutingInfo}
{actionBtn}
diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss
index dd82ab375..0b49da1ad 100644
--- a/app/javascript/styles/mastodon/accounts.scss
+++ b/app/javascript/styles/mastodon/accounts.scss
@@ -563,3 +563,57 @@
border-color: rgba(lighten($error-red, 12%), 0.5);
}
}
+
+.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%);
+
+ th,
+ td {
+ padding: 15px;
+ padding-left: 15px;
+ border: 0 none;
+ border-bottom: 1px solid lighten($ui-base-color, 4%);
+ vertical-align: middle;
+ }
+
+ th {
+ padding-left: 15px;
+ font-weight: 500;
+ text-align: center;
+ width: 94px;
+ color: $ui-secondary-color;
+ background: rgba(darken($ui-base-color, 8%), 0.5);
+ }
+
+ td {
+ color: $ui-primary-color;
+ text-align: center;
+ width: 100%;
+ padding-left: 0;
+ }
+
+ a {
+ color: $ui-highlight-color;
+ text-decoration: none;
+
+ &:hover,
+ &:focus,
+ &:active {
+ text-decoration: underline;
+ }
+ }
+
+ tr {
+ &:last-child {
+ th,
+ td {
+ border-bottom: 0;
+ }
+ }
+ }
+}
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 888a0ad82..96112d84a 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -5176,3 +5176,40 @@ noscript {
background: lighten($ui-highlight-color, 7%);
}
}
+
+.account__header .account__header__fields {
+ font-size: 14px;
+ line-height: 20px;
+ overflow: hidden;
+ border-collapse: collapse;
+ margin: 20px -10px -20px;
+ border-bottom: 0;
+
+ tr {
+ border-top: 1px solid lighten($ui-base-color, 8%);
+ text-align: center;
+ }
+
+ th,
+ td {
+ padding: 14px 20px;
+ vertical-align: middle;
+ max-height: 40px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+
+ th {
+ color: $ui-primary-color;
+ background: darken($ui-base-color, 4%);
+ max-width: 120px;
+ font-weight: 500;
+ }
+
+ td {
+ flex: auto;
+ color: $primary-text-color;
+ background: $ui-base-color;
+ }
+}
diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss
index d74c5a4fd..945579a9c 100644
--- a/app/javascript/styles/mastodon/forms.scss
+++ b/app/javascript/styles/mastodon/forms.scss
@@ -15,6 +15,18 @@ code {
overflow: hidden;
}
+ .row {
+ display: flex;
+ margin: 0 -5px;
+
+ .input {
+ box-sizing: border-box;
+ flex: 1 1 auto;
+ width: 50%;
+ padding: 0 5px;
+ }
+ }
+
span.hint {
display: block;
color: $ui-primary-color;
diff --git a/app/lib/activitypub/adapter.rb b/app/lib/activitypub/adapter.rb
index f19b04ae6..e880499f1 100644
--- a/app/lib/activitypub/adapter.rb
+++ b/app/lib/activitypub/adapter.rb
@@ -19,6 +19,9 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base
'Emoji' => 'toot:Emoji',
'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' },
'featured' => 'toot:featured',
+ 'schema' => 'http://schema.org#',
+ 'PropertyValue' => 'schema:PropertyValue',
+ 'value' => 'schema:value',
},
],
}.freeze
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index f7e7a3c23..4124f1660 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -71,6 +71,11 @@ class Formatter
html.html_safe # rubocop:disable Rails/OutputSafety
end
+ def format_field(account, str)
+ return reformat(str).html_safe unless account.local? # rubocop:disable Rails/OutputSafety
+ encode_and_link_urls(str, me: true).html_safe # rubocop:disable Rails/OutputSafety
+ end
+
def linkify(text)
html = encode_and_link_urls(text)
html = simple_format(html, {}, sanitize: false)
@@ -85,12 +90,17 @@ class Formatter
HTMLEntities.new.encode(html)
end
- def encode_and_link_urls(html, accounts = nil)
+ def encode_and_link_urls(html, accounts = nil, options = {})
entities = Extractor.extract_entities_with_indices(html, extract_url_without_protocol: false)
+ if accounts.is_a?(Hash)
+ options = accounts
+ accounts = nil
+ end
+
rewrite(html.dup, entities) do |entity|
if entity[:url]
- link_to_url(entity)
+ link_to_url(entity, options)
elsif entity[:hashtag]
link_to_hashtag(entity)
elsif entity[:screen_name]
@@ -177,10 +187,12 @@ class Formatter
result.flatten.join
end
- def link_to_url(entity)
+ def link_to_url(entity, options = {})
url = Addressable::URI.parse(entity[:url])
html_attrs = { target: '_blank', rel: 'nofollow noopener' }
+ html_attrs[:rel] = "me #{html_attrs[:rel]}" if options[:me]
+
Twitter::Autolink.send(:link_to_text, entity, link_html(entity[:url]), url, html_attrs)
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
encode(entity[:url])
diff --git a/app/models/account.rb b/app/models/account.rb
index 5bdcfa99e..05e817f63 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -44,6 +44,7 @@
# memorial :boolean default(FALSE), not null
# moved_to_account_id :integer
# featured_collection_url :string
+# fields :jsonb
#
class Account < ApplicationRecord
@@ -189,6 +190,30 @@ class Account < ApplicationRecord
@keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key)
end
+ def fields
+ (self[:fields] || []).map { |f| Field.new(self, f) }
+ end
+
+ def fields_attributes=(attributes)
+ fields = []
+
+ attributes.each_value do |attr|
+ next if attr[:name].blank?
+ fields << attr
+ end
+
+ self[:fields] = fields
+ end
+
+ def build_fields
+ return if fields.size >= 4
+
+ raw_fields = self[:fields] || []
+ add_fields = 4 - raw_fields.size
+ add_fields.times { raw_fields << { name: '', value: '' } }
+ self.fields = raw_fields
+ end
+
def magic_key
modulus, exponent = [keypair.public_key.n, keypair.public_key.e].map do |component|
result = []
@@ -238,6 +263,17 @@ class Account < ApplicationRecord
shared_inbox_url.presence || inbox_url
end
+ class Field < ActiveModelSerializers::Model
+ attributes :name, :value, :account, :errors
+
+ def initialize(account, attr)
+ @account = account
+ @name = attr['name']
+ @value = attr['value']
+ @errors = {}
+ end
+ end
+
class << self
def readonly_attributes
super - %w(statuses_count following_count followers_count)
diff --git a/app/serializers/activitypub/actor_serializer.rb b/app/serializers/activitypub/actor_serializer.rb
index df3090726..fcf3bdf17 100644
--- a/app/serializers/activitypub/actor_serializer.rb
+++ b/app/serializers/activitypub/actor_serializer.rb
@@ -11,6 +11,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
has_one :public_key, serializer: ActivityPub::PublicKeySerializer
has_many :virtual_tags, key: :tag
+ has_many :virtual_attachments, key: :attachment
attribute :moved_to, if: :moved?
@@ -107,10 +108,26 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer
object.emojis
end
+ def virtual_attachments
+ object.fields
+ end
+
def moved_to
ActivityPub::TagManager.instance.uri_for(object.moved_to_account)
end
class CustomEmojiSerializer < ActivityPub::EmojiSerializer
end
+
+ class Account::FieldSerializer < ActiveModel::Serializer
+ attributes :type, :name, :value
+
+ def type
+ 'PropertyValue'
+ end
+
+ def value
+ Formatter.instance.format_field(object.account, object.value)
+ end
+ end
end
diff --git a/app/serializers/rest/account_serializer.rb b/app/serializers/rest/account_serializer.rb
index 6097acda5..863238eb7 100644
--- a/app/serializers/rest/account_serializer.rb
+++ b/app/serializers/rest/account_serializer.rb
@@ -9,6 +9,16 @@ class REST::AccountSerializer < ActiveModel::Serializer
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
+ class FieldSerializer < ActiveModel::Serializer
+ attributes :name, :value
+
+ def value
+ Formatter.instance.format_field(object.account, object.value)
+ end
+ end
+
+ has_many :fields
+
def id
object.id.to_s
end
diff --git a/app/services/activitypub/process_account_service.rb b/app/services/activitypub/process_account_service.rb
index 4475a9079..da32f9615 100644
--- a/app/services/activitypub/process_account_service.rb
+++ b/app/services/activitypub/process_account_service.rb
@@ -70,6 +70,7 @@ class ActivityPub::ProcessAccountService < BaseService
@account.display_name = @json['name'] || ''
@account.note = @json['summary'] || ''
@account.locked = @json['manuallyApprovesFollowers'] || false
+ @account.fields = property_values || {}
end
def set_fetchable_attributes!
@@ -126,6 +127,11 @@ class ActivityPub::ProcessAccountService < BaseService
end
end
+ def property_values
+ return unless @json['attachment'].is_a?(Array)
+ @json['attachment'].select { |attachment| attachment['type'] == 'PropertyValue' }.map { |attachment| attachment.slice('name', 'value') }
+ end
+
def mismatching_origin?(url)
needle = Addressable::URI.parse(url).host
haystack = Addressable::URI.parse(@uri).host
diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml
index b78998e9e..0d3a0d08d 100644
--- a/app/views/accounts/_header.html.haml
+++ b/app/views/accounts/_header.html.haml
@@ -23,6 +23,14 @@
.bio
.account__header__content.p-note.emojify= Formatter.instance.simplified_format(account, custom_emojify: true)
+ - unless account.fields.empty?
+ %table.account__header__fields
+ %tbody
+ - account.fields.each do |field|
+ %tr
+ %th.emojify= field.name
+ %td.emojify= Formatter.instance.format_field(account, field.value)
+
.details-counters
.counter{ class: active_nav_class(short_account_url(account)) }
= link_to short_account_url(account), class: 'u-url u-uid' do
diff --git a/app/views/settings/profiles/show.html.haml b/app/views/settings/profiles/show.html.haml
index 0fc9db2b9..f28834d72 100644
--- a/app/views/settings/profiles/show.html.haml
+++ b/app/views/settings/profiles/show.html.haml
@@ -19,6 +19,16 @@
.fields-group
= f.input :locked, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.locked')
+ .fields-group
+ .input.with_block_label
+ %label= t('simple_form.labels.defaults.fields')
+ %span.hint= t('simple_form.hints.defaults.fields')
+
+ = f.simple_fields_for :fields do |fields_f|
+ .row
+ = fields_f.input :name, placeholder: t('simple_form.labels.account.fields.name')
+ = fields_f.input :value, placeholder: t('simple_form.labels.account.fields.value')
+
.actions
= f.button :button, t('generic.save_changes'), type: :submit
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 37a02bde6..1a0d60f71 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -8,6 +8,7 @@ en:
display_name:
one: 1 character left
other: %{count} characters left
+ fields: You can have up to 4 items displayed as a table on your profile
header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px
locked: Requires you to manually approve followers
note:
@@ -22,6 +23,10 @@ en:
user:
filtered_languages: Checked languages will be filtered from public timelines for you
labels:
+ account:
+ fields:
+ name: Label
+ value: Content
defaults:
avatar: Avatar
confirm_new_password: Confirm new password
@@ -31,6 +36,7 @@ en:
display_name: Display name
email: E-mail address
expires_in: Expire after
+ fields: Profile metadata
filtered_languages: Filtered languages
header: Header
locale: Language
diff --git a/db/migrate/20180410204633_add_fields_to_accounts.rb b/db/migrate/20180410204633_add_fields_to_accounts.rb
new file mode 100644
index 000000000..5b8c17480
--- /dev/null
+++ b/db/migrate/20180410204633_add_fields_to_accounts.rb
@@ -0,0 +1,5 @@
+class AddFieldsToAccounts < ActiveRecord::Migration[5.1]
+ def change
+ add_column :accounts, :fields, :jsonb
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 218457e65..10a8f2edc 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2018_04_02_040909) do
+ActiveRecord::Schema.define(version: 2018_04_10_204633) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
@@ -75,6 +75,7 @@ ActiveRecord::Schema.define(version: 2018_04_02_040909) do
t.boolean "memorial", default: false, null: false
t.bigint "moved_to_account_id"
t.string "featured_collection_url"
+ t.jsonb "fields"
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
t.index "lower((username)::text), lower((domain)::text)", name: "index_accounts_on_username_and_domain_lower"
t.index ["uri"], name: "index_accounts_on_uri"
diff --git a/spec/services/activitypub/process_account_service_spec.rb b/spec/services/activitypub/process_account_service_spec.rb
index 84a74c231..15e1f4bb2 100644
--- a/spec/services/activitypub/process_account_service_spec.rb
+++ b/spec/services/activitypub/process_account_service_spec.rb
@@ -1,5 +1,31 @@
require 'rails_helper'
RSpec.describe ActivityPub::ProcessAccountService do
- pending
+ subject { described_class.new }
+
+ context 'property values' do
+ let(:payload) do
+ {
+ id: 'https://foo',
+ type: 'Actor',
+ inbox: 'https://foo/inbox',
+ attachment: [
+ { type: 'PropertyValue', name: 'Pronouns', value: 'They/them' },
+ { type: 'PropertyValue', name: 'Occupation', value: 'Unit test' },
+ ],
+ }.with_indifferent_access
+ end
+
+ it 'parses out of attachment' do
+ account = subject.call('alice', 'example.com', payload)
+ expect(account.fields).to be_a Array
+ expect(account.fields.size).to eq 2
+ expect(account.fields[0]).to be_a Account::Field
+ expect(account.fields[0].name).to eq 'Pronouns'
+ expect(account.fields[0].value).to eq 'They/them'
+ expect(account.fields[1]).to be_a Account::Field
+ expect(account.fields[1].name).to eq 'Occupation'
+ expect(account.fields[1].value).to eq 'Unit test'
+ end
+ end
end
From fed0b5ed0453b0347b27acfb2950d94af870b62b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?=
Date: Sun, 15 Apr 2018 07:12:41 +0200
Subject: [PATCH 076/442] i18n: Update Polish translation (#7131)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marcin Mikołajczak
---
.../mastodon/locales/defaultMessages.json | 13 -------------
app/javascript/mastodon/locales/pl.json | 3 ++-
config/locales/en.yml | 5 +++++
config/locales/pl.yml | 19 +++++++++++++++++++
4 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 21cd83524..a3c4f775c 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -1815,18 +1815,5 @@
}
],
"path": "app/javascript/mastodon/features/video/index.json"
- },
- {
- "descriptors": [
- {
- "defaultMessage": "Oops!",
- "id": "alert.unexpected.title"
- },
- {
- "defaultMessage": "An unexpected error occurred.",
- "id": "alert.unexpected.message"
- }
- ],
- "path": "app/javascript/mastodon/middleware/errors.json"
}
]
\ No newline at end of file
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 041935689..5360b6f33 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -2,7 +2,7 @@
"account.block": "Blokuj @{name}",
"account.block_domain": "Blokuj wszystko z {domain}",
"account.blocked": "Zablokowany",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Wyślij wiadomość bezpośrednią do @{name}",
"account.disclaimer_full": "Poniższe informacje mogą nie odwzorowywać bezbłędnie profilu użytkownika.",
"account.domain_blocked": "Ukryto domenę",
"account.edit_profile": "Edytuj profil",
@@ -240,6 +240,7 @@
"status.block": "Zablokuj @{name}",
"status.cannot_reblog": "Ten wpis nie może zostać podbity",
"status.delete": "Usuń",
+ "status.direct": "Direct message @{name}",
"status.embed": "Osadź",
"status.favourite": "Ulubione",
"status.load_more": "Załaduj więcej",
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 98f135966..4816cc599 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -283,6 +283,7 @@ en:
nsfw:
'false': Unhide media attachments
'true': Hide media attachments
+ reopen: Reopen Report
report: 'Report #%{id}'
report_contents: Contents
reported_account: Reported account
@@ -615,6 +616,10 @@ en:
missing_resource: Could not find the required redirect URL for your account
proceed: Proceed to follow
prompt: 'You are going to follow:'
+ remote_unfollow:
+ error: Error
+ title: Title
+ unfollowed: Unfollowed
sessions:
activity: Last activity
browser: Browser
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index d303171fb..0f18ace37 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -63,6 +63,13 @@ pl:
are_you_sure: Jesteś tego pewien?
avatar: Awatar
by_domain: Domena
+ change_email:
+ changed_msg: Pomyślnie zmieniono adres e-mail konta!
+ current_email: Obecny adres e-mail
+ label: Zmień adres e-mail
+ new_email: Nowy adres e-mail
+ submit: Zmień adres e-mail
+ title: Zmień adres e-mail dla %{username}
confirm: Potwierdź
confirmed: Potwierdzono
demote: Degraduj
@@ -131,6 +138,7 @@ pl:
statuses: Wpisy
subscribe: Subskrybuj
title: Konta
+ unconfirmed_email: Niepotwierdzony adres e-mail
undo_silenced: Cofnij wyciszenie
undo_suspension: Cofnij zawieszenie
unsubscribe: Przestań subskrybować
@@ -139,6 +147,7 @@ pl:
action_logs:
actions:
assigned_to_self_report: "%{name} przypisał sobie zgłoszenie %{target}"
+ change_email_user: "%{name} zmienił adres-email użytkownika %{target}"
confirm_user: "%{name} potwierdził adres e-mail użytkownika %{target}"
create_custom_emoji: "%{name} dodał nowe emoji %{target}"
create_domain_block: "%{name} zablokował domenę %{target}"
@@ -258,18 +267,24 @@ pl:
comment:
label: Komentarz do zgłoszenia
none: Brak
+ created_at: Zgłoszono
delete: Usuń
+ history: Historia moderacji
id: ID
mark_as_resolved: Oznacz jako rozwiązane
mark_as_unresolved: Oznacz jako nierozwiązane
notes:
create: Utwórz notatkę
create_and_resolve: Rozwiąż i pozostaw notatkę
+ create_and_unresolve: Cofnij rozwiązanie i pozostaw notatkę
delete: Usuń
label: Notatki
+ new_label: Dodaj notatkę moderacyjną
+ placeholder: Opisz wykonane akcje i inne szczegóły dotyczące tego zgłoszenia…
nsfw:
'false': Nie oznaczaj jako NSFW
'true': Oznaczaj jako NSFW
+ reopen: Otwórz ponownie
report: 'Zgłoszenie #%{id}'
report_contents: Zawartość
reported_account: Zgłoszone konto
@@ -608,6 +623,10 @@ pl:
missing_resource: Nie udało się znaleźć adresu przekierowania z Twojej domeny
proceed: Śledź
prompt: 'Zamierzasz śledzić:'
+ remote_unfollow:
+ error: Błąd
+ title: Tytuł
+ unfollowed: Przestałeś śledzić
sessions:
activity: Ostatnia aktywność
browser: Przeglądarka
From 1e87ed44d551e1ff9ea9e0d7219386ecf15173cb Mon Sep 17 00:00:00 2001
From: Valentin Lorentz
Date: Sun, 15 Apr 2018 13:57:58 +0200
Subject: [PATCH 077/442] docker-compose: Only bind ports 3000 and 4000 on
localhost. (#7138)
---
docker-compose.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 836cb00b8..8058326dc 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -40,7 +40,7 @@ services:
- external_network
- internal_network
ports:
- - "3000:3000"
+ - "127.0.0.1:3000:3000"
depends_on:
- db
- redis
@@ -60,7 +60,7 @@ services:
- external_network
- internal_network
ports:
- - "4000:4000"
+ - "127.0.0.1:4000:4000"
depends_on:
- db
- redis
From fa04945365bc552748b9d312f936a74cfd8d35b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?=
Date: Sun, 15 Apr 2018 13:58:47 +0200
Subject: [PATCH 078/442] Change icon for domain blocks (#7139)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Change icon for domain blocks
Both domain blocks and user blocks uses the same icon…
* Update index.js
---
app/javascript/mastodon/features/domain_blocks/index.js | 2 +-
app/javascript/mastodon/features/getting_started/index.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/features/domain_blocks/index.js b/app/javascript/mastodon/features/domain_blocks/index.js
index b17c47e91..3b29e2a26 100644
--- a/app/javascript/mastodon/features/domain_blocks/index.js
+++ b/app/javascript/mastodon/features/domain_blocks/index.js
@@ -52,7 +52,7 @@ export default class Blocks extends ImmutablePureComponent {
}
return (
-
+
{domains.map(domain =>
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index 1a71cff94..053a1ca17 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -122,7 +122,7 @@ export default class GettingStarted extends ImmutablePureComponent {
-
+
From 9f5ae7c2e81d898496743e68bc295e42515189aa Mon Sep 17 00:00:00 2001
From: YMHuang
Date: Sun, 15 Apr 2018 12:00:32 +0000
Subject: [PATCH 079/442] Add and revise Traditional Chinese (zh-TW)
translation for serveral strings (#7002)
* Translation: add and revise Traditional Chinese translation for serveral strings
* Translation: polish zh-TW locale
* Translation: polish zh-TW locale
---
app/javascript/mastodon/locales/zh-TW.json | 124 ++++++++++-----------
1 file changed, 62 insertions(+), 62 deletions(-)
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index c7925829f..3edb3fa50 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -1,24 +1,24 @@
{
"account.block": "封鎖 @{name}",
"account.block_domain": "隱藏來自 {domain} 的一切貼文",
- "account.blocked": "Blocked",
- "account.direct": "Direct message @{name}",
+ "account.blocked": "已被封鎖的",
+ "account.direct": "給 @{name} 私人訊息",
"account.disclaimer_full": "下列資料不一定完整。",
- "account.domain_blocked": "Domain hidden",
- "account.edit_profile": "編輯用者資訊",
+ "account.domain_blocked": "域名隱藏",
+ "account.edit_profile": "編輯使用者資訊",
"account.follow": "關注",
- "account.followers": "專注者",
+ "account.followers": "關注者",
"account.follows": "正關注",
"account.follows_you": "關注你",
- "account.hide_reblogs": "Hide boosts from @{name}",
+ "account.hide_reblogs": "隱藏來自 @{name} 的轉推",
"account.media": "媒體",
"account.mention": "提到 @{name}",
- "account.moved_to": "{name} has moved to:",
+ "account.moved_to": "{name} 已經移至:",
"account.mute": "消音 @{name}",
- "account.mute_notifications": "Mute notifications from @{name}",
- "account.muted": "Muted",
+ "account.mute_notifications": "消音來自 @{name} 的通知",
+ "account.muted": "消音的",
"account.posts": "貼文",
- "account.posts_with_replies": "Toots with replies",
+ "account.posts_with_replies": "貼文及回覆",
"account.report": "檢舉 @{name}",
"account.requested": "正在等待許可",
"account.share": "分享 @{name} 的用者資訊",
@@ -27,10 +27,10 @@
"account.unblock_domain": "不再隱藏 {domain}",
"account.unfollow": "取消關注",
"account.unmute": "不再消音 @{name}",
- "account.unmute_notifications": "Unmute notifications from @{name}",
+ "account.unmute_notifications": "不再對來自 @{name} 的通知消音",
"account.view_full_profile": "查看完整資訊",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "發生非預期的錯誤。",
+ "alert.unexpected.title": "哎呀!",
"boost_modal.combo": "下次你可以按 {combo} 來跳過",
"bundle_column_error.body": "加載本組件出錯。",
"bundle_column_error.retry": "重試",
@@ -40,11 +40,11 @@
"bundle_modal_error.retry": "重試",
"column.blocks": "封鎖的使用者",
"column.community": "本地時間軸",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "隱藏域名",
"column.favourites": "最愛",
"column.follow_requests": "關注請求",
"column.home": "家",
- "column.lists": "Lists",
+ "column.lists": "名單",
"column.mutes": "消音的使用者",
"column.notifications": "通知",
"column.pins": "置頂貼文",
@@ -58,17 +58,17 @@
"column_header.unpin": "取下",
"column_subheading.navigation": "瀏覽",
"column_subheading.settings": "設定",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
- "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.direct_message_warning": "此則推文只會被所有提到的使用者看見。",
+ "compose_form.hashtag_warning": "此則推文將不會在任何主題標籤中看見,只有公開的推文可以用主題標籤來搜尋。",
"compose_form.lock_disclaimer": "你的帳號沒有{locked}。任何人都可以關注你,看到發給關注者的貼文。",
"compose_form.lock_disclaimer.lock": "上鎖",
"compose_form.placeholder": "在想些什麼?",
"compose_form.publish": "貼掉",
"compose_form.publish_loud": "{publish}!",
- "compose_form.sensitive.marked": "Media is marked as sensitive",
- "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
- "compose_form.spoiler.marked": "Text is hidden behind warning",
- "compose_form.spoiler.unmarked": "Text is not hidden",
+ "compose_form.sensitive.marked": "此媒體已被標註為敏感的",
+ "compose_form.sensitive.unmarked": "此媒體未被標註為敏感的",
+ "compose_form.spoiler.marked": "文字隱藏在警告後",
+ "compose_form.spoiler.unmarked": "文字不是隱藏的",
"compose_form.spoiler_placeholder": "內容警告",
"confirmation_modal.cancel": "取消",
"confirmations.block.confirm": "封鎖",
@@ -86,17 +86,17 @@
"embed.instructions": "要內嵌此貼文,請將以下代碼貼進你的網站。",
"embed.preview": "看上去會變成這樣:",
"emoji_button.activity": "活動",
- "emoji_button.custom": "Custom",
+ "emoji_button.custom": "自訂",
"emoji_button.flags": "旗幟",
- "emoji_button.food": "食物與飲料",
+ "emoji_button.food": "飲食",
"emoji_button.label": "插入表情符號",
"emoji_button.nature": "自然",
- "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
+ "emoji_button.not_found": "沒有表情符號吼!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "物件",
"emoji_button.people": "人",
- "emoji_button.recent": "Frequently used",
+ "emoji_button.recent": "常用",
"emoji_button.search": "搜尋…",
- "emoji_button.search_results": "Search results",
+ "emoji_button.search_results": "搜尋結果",
"emoji_button.symbols": "符號",
"emoji_button.travel": "旅遊與地點",
"empty_column.community": "本地時間軸是空的。公開寫點什麼吧!",
@@ -108,8 +108,8 @@
"empty_column.public": "這裡什麼都沒有!公開寫些什麼,或是關注其他副本的使用者。",
"follow_request.authorize": "授權",
"follow_request.reject": "拒絕",
- "getting_started.appsshort": "Apps",
- "getting_started.faq": "FAQ",
+ "getting_started.appsshort": "應用程式",
+ "getting_started.faq": "常見問答",
"getting_started.heading": "馬上開始",
"getting_started.open_source_notice": "Mastodon 是開源軟體。你可以在 GitHub {github} 上做出貢獻或是回報問題。",
"getting_started.userguide": "使用者指南",
@@ -119,19 +119,19 @@
"home.column_settings.show_reblogs": "顯示轉推",
"home.column_settings.show_replies": "顯示回應",
"home.settings": "欄位設定",
- "keyboard_shortcuts.back": "to navigate back",
- "keyboard_shortcuts.boost": "to boost",
+ "keyboard_shortcuts.back": "回到上一個",
+ "keyboard_shortcuts.boost": "到轉推",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
- "keyboard_shortcuts.compose": "to focus the compose textarea",
- "keyboard_shortcuts.description": "Description",
+ "keyboard_shortcuts.compose": "焦點移至撰寫文字區塊",
+ "keyboard_shortcuts.description": "描述",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.enter": "to open status",
- "keyboard_shortcuts.favourite": "to favourite",
- "keyboard_shortcuts.heading": "Keyboard Shortcuts",
- "keyboard_shortcuts.hotkey": "Hotkey",
+ "keyboard_shortcuts.favourite": "收藏",
+ "keyboard_shortcuts.heading": "鍵盤快速鍵",
+ "keyboard_shortcuts.hotkey": "快速鍵",
"keyboard_shortcuts.legend": "to display this legend",
- "keyboard_shortcuts.mention": "to mention author",
- "keyboard_shortcuts.reply": "to reply",
+ "keyboard_shortcuts.mention": "到提到的作者",
+ "keyboard_shortcuts.reply": "到回應",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
@@ -150,11 +150,11 @@
"loading_indicator.label": "讀取中...",
"media_gallery.toggle_visible": "切換可見性",
"missing_indicator.label": "找不到",
- "missing_indicator.sublabel": "This resource could not be found",
- "mute_modal.hide_notifications": "Hide notifications from this user?",
+ "missing_indicator.sublabel": "找不到此資源",
+ "mute_modal.hide_notifications": "隱藏來自這個使用者的通知?",
"navigation_bar.blocks": "封鎖的使用者",
"navigation_bar.community_timeline": "本地時間軸",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "隱藏的域名",
"navigation_bar.edit_profile": "編輯用者資訊",
"navigation_bar.favourites": "最愛",
"navigation_bar.follow_requests": "關注請求",
@@ -197,7 +197,7 @@
"onboarding.page_six.github": "Mastodon 是自由的開源軟體。你可以在 {github} 上回報臭蟲、請求新功能或是做出貢獻。",
"onboarding.page_six.guidelines": "社群指南",
"onboarding.page_six.read_guidelines": "請閱讀 {domain} 的 {guidelines} !",
- "onboarding.page_six.various_app": "行動 apps",
+ "onboarding.page_six.various_app": "行動版應用程式",
"onboarding.page_three.profile": "編輯你的大頭貼、自傳和顯示名稱。你也可以在這邊找到其他設定。",
"onboarding.page_three.search": "利用搜尋列來找到其他人或是主題標籤,像是 {illustration} 或 {introductions} 。用完整的帳號名稱來找不在這個副本上的使用者。",
"onboarding.page_two.compose": "在編輯欄寫些什麼。可以上傳圖片、改變隱私設定或是用下面的圖示加上內容警告。",
@@ -211,13 +211,13 @@
"privacy.public.short": "公開貼",
"privacy.unlisted.long": "不要貼到公開時間軸",
"privacy.unlisted.short": "不列出來",
- "regeneration_indicator.label": "Loading…",
+ "regeneration_indicator.label": "載入中…",
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
- "relative_time.days": "{number}d",
- "relative_time.hours": "{number}h",
- "relative_time.just_now": "now",
- "relative_time.minutes": "{number}m",
- "relative_time.seconds": "{number}s",
+ "relative_time.days": "{number} 天",
+ "relative_time.hours": "{number} 時",
+ "relative_time.just_now": "現在",
+ "relative_time.minutes": "{number} 分",
+ "relative_time.seconds": "{number} 秒",
"reply_indicator.cancel": "取消",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
@@ -226,18 +226,18 @@
"report.submit": "送出",
"report.target": "通報中",
"search.placeholder": "搜尋",
- "search_popout.search_format": "Advanced search format",
+ "search_popout.search_format": "進階搜尋格式",
"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": "status",
+ "search_popout.tips.hashtag": "主題標籤",
+ "search_popout.tips.status": "狀態",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
- "search_popout.tips.user": "user",
- "search_results.accounts": "People",
- "search_results.hashtags": "Hashtags",
- "search_results.statuses": "Toots",
+ "search_popout.tips.user": "使用者",
+ "search_results.accounts": "人",
+ "search_results.hashtags": "主題標籤",
+ "search_results.statuses": "推文",
"search_results.total": "{count, number} 項結果",
"standalone.public_title": "站點一瞥…",
- "status.block": "Block @{name}",
+ "status.block": "封鎖 @{name}",
"status.cannot_reblog": "此貼文無法轉推",
"status.delete": "刪除",
"status.embed": "Embed",
@@ -250,7 +250,7 @@
"status.mute_conversation": "消音對話",
"status.open": "展開這個狀態",
"status.pin": "置頂到個人資訊頁",
- "status.pinned": "Pinned toot",
+ "status.pinned": "置頂的推文",
"status.reblog": "轉推",
"status.reblogged_by": "{name} 轉推了",
"status.reply": "回應",
@@ -258,7 +258,7 @@
"status.report": "通報 @{name}",
"status.sensitive_toggle": "點來看",
"status.sensitive_warning": "敏感內容",
- "status.share": "Share",
+ "status.share": "分享",
"status.show_less": "看少點",
"status.show_less_all": "Show less for all",
"status.show_more": "看更多",
@@ -269,17 +269,17 @@
"tabs_bar.home": "家",
"tabs_bar.local_timeline": "本地",
"tabs_bar.notifications": "通知",
- "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
+ "ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。",
"upload_area.title": "拖放來上傳",
"upload_button.label": "增加媒體",
- "upload_form.description": "Describe for the visually impaired",
- "upload_form.focus": "Crop",
+ "upload_form.description": "爲視障者加上描述",
+ "upload_form.focus": "裁切",
"upload_form.undo": "復原",
"upload_progress.label": "上傳中...",
"video.close": "關閉影片",
- "video.exit_fullscreen": "退出全熒幕",
+ "video.exit_fullscreen": "退出全螢幕",
"video.expand": "展開影片",
- "video.fullscreen": "全熒幕",
+ "video.fullscreen": "全螢幕",
"video.hide": "隱藏影片",
"video.mute": "消音",
"video.pause": "暫停",
From 7c43ed04fec0603073fe0b5a687992cab684a3b5 Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Sun, 15 Apr 2018 23:56:03 +0900
Subject: [PATCH 080/442] Weblate translations (2018-04-15) (#7141)
* Translated using Weblate (Galician)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ca/
* Translated using Weblate (Arabic)
Currently translated at 76.4% (449 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Slovak)
Currently translated at 92.3% (542 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 92.3% (542 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/sk/
* Translated using Weblate (Polish)
Currently translated at 98.9% (581 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pl/
* Translated using Weblate (French)
Currently translated at 99.6% (585 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/
* Translated using Weblate (Persian)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/fa/
* Translated using Weblate (Persian)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fa/
* Translated using Weblate (French)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/zh_Hant/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/zh_Hant/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/zh_Hant/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/zh_Hant/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eo/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/zh_Hant/
* Translated using Weblate (Arabic)
Currently translated at 76.6% (450 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eo/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Slovak)
Currently translated at 92.6% (544 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/sk/
* Translated using Weblate (Arabic)
Currently translated at 82.9% (487 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Arabic)
Currently translated at 98.6% (74 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/ar/
* Translated using Weblate (Slovak)
Currently translated at 93.6% (550 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 95.4% (560 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Japanese)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/
* Translated using Weblate (Indonesian)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/id/
* Translated using Weblate (Korean)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ko/
* Translated using Weblate (Korean)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ko/
* Translated using Weblate (Korean)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ko/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Arabic)
Currently translated at 82.9% (487 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Arabic)
Currently translated at 99.2% (278 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/
* Translated using Weblate (Arabic)
Currently translated at 87.3% (513 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Arabic)
Currently translated at 99.6% (279 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/sk/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fi/
* Translated using Weblate (Arabic)
Currently translated at 88.0% (517 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fi/
* Translated using Weblate (Japanese)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/
* Translated using Weblate (Spanish)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/es/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/fi/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eo/
* Translated using Weblate (Slovak)
Currently translated at 95.4% (560 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/sk/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/fi/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/eo/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/sk/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/fi/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/fi/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fi/
* Translated using Weblate (Finnish)
Currently translated at 100.0% (58 of 58 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fi/
* Translated using Weblate (Finnish)
Currently translated at 25.8% (152 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fi/
* Translated using Weblate (Finnish)
Currently translated at 25.8% (152 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fi/
* Translated using Weblate (Japanese)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Finnish)
Currently translated at 33.0% (194 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fi/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eo/
* Translated using Weblate (Finnish)
Currently translated at 99.8% (586 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fi/
* Translated using Weblate (Slovak)
Currently translated at 95.5% (561 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Esperanto)
Currently translated at 100.0% (587 of 587 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eo/
* Translated using Weblate (Galician)
Currently translated at 100.0% (280 of 280 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/gl/
* yarn manage:translations
---
app/javascript/mastodon/locales/ar.json | 2 +
app/javascript/mastodon/locales/bg.json | 2 +
app/javascript/mastodon/locales/ca.json | 2 +
app/javascript/mastodon/locales/de.json | 2 +
app/javascript/mastodon/locales/eo.json | 14 +-
app/javascript/mastodon/locales/es.json | 2 +
app/javascript/mastodon/locales/fa.json | 2 +
app/javascript/mastodon/locales/fi.json | 228 +++---
app/javascript/mastodon/locales/fr.json | 2 +
app/javascript/mastodon/locales/gl.json | 6 +-
app/javascript/mastodon/locales/he.json | 2 +
app/javascript/mastodon/locales/hr.json | 2 +
app/javascript/mastodon/locales/hu.json | 2 +
app/javascript/mastodon/locales/hy.json | 2 +
app/javascript/mastodon/locales/id.json | 2 +
app/javascript/mastodon/locales/io.json | 2 +
app/javascript/mastodon/locales/it.json | 2 +
app/javascript/mastodon/locales/ja.json | 2 +-
app/javascript/mastodon/locales/ko.json | 2 +
app/javascript/mastodon/locales/nl.json | 2 +
app/javascript/mastodon/locales/no.json | 2 +
app/javascript/mastodon/locales/oc.json | 2 +
app/javascript/mastodon/locales/pt-BR.json | 2 +
app/javascript/mastodon/locales/pt.json | 2 +
app/javascript/mastodon/locales/ru.json | 2 +
app/javascript/mastodon/locales/sk.json | 28 +-
app/javascript/mastodon/locales/sr-Latn.json | 2 +
app/javascript/mastodon/locales/sr.json | 2 +
app/javascript/mastodon/locales/sv.json | 2 +
app/javascript/mastodon/locales/th.json | 2 +
app/javascript/mastodon/locales/tr.json | 2 +
app/javascript/mastodon/locales/uk.json | 2 +
app/javascript/mastodon/locales/zh-CN.json | 2 +
app/javascript/mastodon/locales/zh-HK.json | 2 +
app/javascript/mastodon/locales/zh-TW.json | 2 +
config/locales/ar.yml | 4 +
config/locales/devise.fi.yml | 91 ++-
config/locales/devise.sk.yml | 10 +-
config/locales/doorkeeper.fi.yml | 108 +--
config/locales/doorkeeper.sk.yml | 2 +-
config/locales/eo.yml | 6 +-
config/locales/es.yml | 13 +-
config/locales/fi.yml | 698 ++++++++++++++++---
config/locales/ja.yml | 2 +-
config/locales/simple_form.eo.yml | 4 +-
config/locales/simple_form.fi.yml | 66 +-
config/locales/simple_form.sk.yml | 16 +-
config/locales/sk.yml | 27 +-
48 files changed, 1011 insertions(+), 374 deletions(-)
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 34e34411f..c13ff773d 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "تعذرت ترقية هذا المنشور",
"status.delete": "إحذف",
+ "status.direct": "Direct message @{name}",
"status.embed": "إدماج",
"status.favourite": "أضف إلى المفضلة",
"status.load_more": "حمّل المزيد",
@@ -269,6 +270,7 @@
"tabs_bar.home": "الرئيسية",
"tabs_bar.local_timeline": "المحلي",
"tabs_bar.notifications": "الإخطارات",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "سوف تفقد مسودتك إن تركت ماستدون.",
"upload_area.title": "إسحب ثم أفلت للرفع",
"upload_button.label": "إضافة وسائط",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 9aaff0ddf..981aced0b 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Изтриване",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Предпочитани",
"status.load_more": "Load more",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Начало",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Известия",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Добави медия",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index b7f95a664..d9270e0ce 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Aquesta publicació no pot ser retootejada",
"status.delete": "Esborrar",
+ "status.direct": "Direct message @{name}",
"status.embed": "Incrustar",
"status.favourite": "Favorit",
"status.load_more": "Carrega més",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Inici",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificacions",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "El vostre esborrany es perdrà si sortiu de Mastodon.",
"upload_area.title": "Arrossega i deixa anar per carregar",
"upload_button.label": "Afegir multimèdia",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index a618b853e..6eb5e6840 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden",
"status.delete": "Löschen",
+ "status.direct": "Direct message @{name}",
"status.embed": "Einbetten",
"status.favourite": "Favorisieren",
"status.load_more": "Weitere laden",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Startseite",
"tabs_bar.local_timeline": "Lokal",
"tabs_bar.notifications": "Mitteilungen",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Zum Hochladen hereinziehen",
"upload_button.label": "Mediendatei hinzufügen",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 6dee6e544..19f3c5907 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -60,7 +60,7 @@
"column_subheading.settings": "Agordado",
"compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
"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 nur por sekvantoj.",
+ "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",
"compose_form.placeholder": "Pri kio vi pensas?",
"compose_form.publish": "Hup",
@@ -102,7 +102,7 @@
"empty_column.community": "La loka tempolinio estas malplena. Skribu ion por plenigi ĝin!",
"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 publika tempolinio",
+ "empty_column.home.public_timeline": "la publikan tempolinion",
"empty_column.list": "Ankoraŭ estas nenio en ĉi tiu listo. Kiam membroj de ĉi tiu listo afiŝos novajn mesaĝojn, ili aperos ĉi tie.",
"empty_column.notifications": "Vi ankoraŭ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.",
"empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj nodoj por plenigi la publikan tempolinion",
@@ -150,8 +150,8 @@
"loading_indicator.label": "Ŝargado…",
"media_gallery.toggle_visible": "Baskuligi videblecon",
"missing_indicator.label": "Ne trovita",
- "missing_indicator.sublabel": "Ĉi tiu rimedo ne estis trovita",
- "mute_modal.hide_notifications": "Ĉu kaŝi sciigojn el ĉi tiu uzanto?",
+ "missing_indicator.sublabel": "Ĉi tiu elemento ne estis trovita",
+ "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.domain_blocks": "Hidden domains",
@@ -240,6 +240,7 @@
"status.block": "Bloki @{name}",
"status.cannot_reblog": "Ĉi tiu mesaĝo ne diskonigeblas",
"status.delete": "Forigi",
+ "status.direct": "Direct message @{name}",
"status.embed": "Enkorpigi",
"status.favourite": "Stelumi",
"status.load_more": "Ŝargi pli",
@@ -248,8 +249,8 @@
"status.more": "Pli",
"status.mute": "Silentigi @{name}",
"status.mute_conversation": "Silentigi konversacion",
- "status.open": "Grandigi ĉi tiun mesaĝon",
- "status.pin": "Alpingli en la profilo",
+ "status.open": "Grandigi",
+ "status.pin": "Alpingli profile",
"status.pinned": "Alpinglita mesaĝo",
"status.reblog": "Diskonigi",
"status.reblogged_by": "{name} diskonigis",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Hejmo",
"tabs_bar.local_timeline": "Loka tempolinio",
"tabs_bar.notifications": "Sciigoj",
+ "tabs_bar.search": "Search",
"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/es.json b/app/javascript/mastodon/locales/es.json
index 6f9c06c5f..e765cc078 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Este toot no puede retootearse",
"status.delete": "Borrar",
+ "status.direct": "Direct message @{name}",
"status.embed": "Incrustado",
"status.favourite": "Favorito",
"status.load_more": "Cargar más",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Inicio",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificaciones",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
"upload_area.title": "Arrastra y suelta para subir",
"upload_button.label": "Subir multimedia",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 61cdcd00a..822c998ce 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "این نوشته را نمیشود بازبوقید",
"status.delete": "پاککردن",
+ "status.direct": "Direct message @{name}",
"status.embed": "جاگذاری",
"status.favourite": "پسندیدن",
"status.load_more": "بیشتر نشان بده",
@@ -269,6 +270,7 @@
"tabs_bar.home": "خانه",
"tabs_bar.local_timeline": "محلی",
"tabs_bar.notifications": "اعلانها",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "اگر از ماستدون خارج شوید پیشنویس شما پاک خواهد شد.",
"upload_area.title": "برای بارگذاری به اینجا بکشید",
"upload_button.label": "افزودن تصویر",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index f4be80514..5763ac442 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -2,7 +2,7 @@
"account.block": "Estä @{name}",
"account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}",
"account.blocked": "Estetty",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "Alla olevat käyttäjän profiilitiedot saattavat olla epätäydellisiä.",
"account.domain_blocked": "Verkko-osoite piilotettu",
"account.edit_profile": "Muokkaa",
@@ -17,37 +17,37 @@
"account.mute": "Mykistä @{name}",
"account.mute_notifications": "Mykistä ilmoitukset käyttäjältä @{name}",
"account.muted": "Mykistetty",
- "account.posts": "Töötit",
- "account.posts_with_replies": "Töötit ja vastaukset",
- "account.report": "Report @{name}",
- "account.requested": "Odottaa hyväksyntää. Klikkaa peruuttaaksesi seurauspyynnön",
+ "account.posts": "Tuuttaukset",
+ "account.posts_with_replies": "Tuuttaukset ja vastaukset",
+ "account.report": "Raportoi @{name}",
+ "account.requested": "Odottaa hyväksyntää. Peruuta seuraamispyyntö klikkaamalla",
"account.share": "Jaa käyttäjän @{name} profiili",
- "account.show_reblogs": "Näytä boostaukset käyttäjältä @{name}",
+ "account.show_reblogs": "Näytä buustaukset käyttäjältä @{name}",
"account.unblock": "Salli @{name}",
"account.unblock_domain": "Näytä {domain}",
"account.unfollow": "Lakkaa seuraamasta",
- "account.unmute": "Poista mykistys käyttäjältä @{name}",
+ "account.unmute": "Poista käyttäjän @{name} mykistys",
"account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta",
"account.view_full_profile": "Näytä koko profiili",
"alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!",
- "boost_modal.combo": "Voit painaa näppäimiä {combo} ohittaaksesi tämän ensi kerralla",
- "bundle_column_error.body": "Jokin meni vikaan tätä komponenttia ladatessa.",
+ "boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}",
+ "bundle_column_error.body": "Jokin meni vikaan komponenttia ladattaessa.",
"bundle_column_error.retry": "Yritä uudestaan",
- "bundle_column_error.title": "Network error",
+ "bundle_column_error.title": "Verkkovirhe",
"bundle_modal_error.close": "Sulje",
- "bundle_modal_error.message": "Jokin meni vikaan tätä komponenttia ladatessa.",
+ "bundle_modal_error.message": "Jokin meni vikaan komponenttia ladattaessa.",
"bundle_modal_error.retry": "Yritä uudestaan",
"column.blocks": "Estetyt käyttäjät",
"column.community": "Paikallinen aikajana",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Suosikit",
- "column.follow_requests": "Seurauspyynnöt",
+ "column.follow_requests": "Seuraamispyynnöt",
"column.home": "Koti",
"column.lists": "Listat",
"column.mutes": "Mykistetyt käyttäjät",
"column.notifications": "Ilmoitukset",
- "column.pins": "Pinned toot",
+ "column.pins": "Kiinnitetty tuuttaus",
"column.public": "Yleinen aikajana",
"column_back_button.label": "Takaisin",
"column_header.hide_settings": "Piilota asetukset",
@@ -59,32 +59,32 @@
"column_subheading.navigation": "Navigaatio",
"column_subheading.settings": "Asetukset",
"compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
- "compose_form.hashtag_warning": "Tämä töötti ei tule näkymään hashtag-hauissa, koska se ei näy julkisilla aikajanoilla. Vain julkisia tööttejä voi hakea hashtageilla.",
- "compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille -postauksesi.",
+ "compose_form.hashtag_warning": "Tämä tuuttaus ei näy hashtag-hauissa, koska se on listaamaton. Hashtagien avulla voi hakea vain julkisia tuuttauksia.",
+ "compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille rajaamasi julkaisut.",
"compose_form.lock_disclaimer.lock": "lukittu",
- "compose_form.placeholder": "Mitä sinulla on mielessä?",
- "compose_form.publish": "Toot",
+ "compose_form.placeholder": "Mitä mietit?",
+ "compose_form.publish": "Tuuttaa",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "Media on merkitty arkaluontoiseksi",
"compose_form.sensitive.unmarked": "Mediaa ei ole merkitty arkaluontoiseksi",
"compose_form.spoiler.marked": "Teksti on piilotettu varoituksen taakse",
"compose_form.spoiler.unmarked": "Teksti ei ole piilotettu",
- "compose_form.spoiler_placeholder": "Content warning",
+ "compose_form.spoiler_placeholder": "Sisältövaroitus",
"confirmation_modal.cancel": "Peruuta",
"confirmations.block.confirm": "Estä",
- "confirmations.block.message": "Oletko varma, että haluat estää käyttäjän {name}?",
- "confirmations.delete.confirm": "Delete",
- "confirmations.delete.message": "Oletko varma, että haluat poistaa tämän statuspäivityksen?",
- "confirmations.delete_list.confirm": "Delete",
- "confirmations.delete_list.message": "Oletko varma, että haluat poistaa tämän listan pysyvästi?",
+ "confirmations.block.message": "Haluatko varmasti estää käyttäjän {name}?",
+ "confirmations.delete.confirm": "Poista",
+ "confirmations.delete.message": "Haluatko varmasti poistaa tämän tilapäivityksen?",
+ "confirmations.delete_list.confirm": "Poista",
+ "confirmations.delete_list.message": "Haluatko varmasti poistaa tämän listan kokonaan?",
"confirmations.domain_block.confirm": "Piilota koko verkko-osoite",
- "confirmations.domain_block.message": "Oletko aivan oikeasti varma että haluat estää koko verkko-osoitteen {domain}? Useimmissa tapauksissa muutamat kohdistetut estot ja mykistykset ovat riittäviä ja suositeltavampia.",
+ "confirmations.domain_block.message": "Haluatko aivan varmasti estää koko verkko-osoitteen {domain}? Useimmiten jokunen kohdistettu esto ja mykistys riittää, ja se on suositeltavampi tapa toimia.",
"confirmations.mute.confirm": "Mykistä",
- "confirmations.mute.message": "Oletko varma että haluat mykistää käyttäjän {name}?",
+ "confirmations.mute.message": "Haluatko varmasti mykistää käyttäjän {name}?",
"confirmations.unfollow.confirm": "Lakkaa seuraamasta",
- "confirmations.unfollow.message": "Oletko varma, että haluat lakata seuraamasta käyttäjää {name}?",
- "embed.instructions": "Upota tämä statuspäivitys sivullesi kopioimalla alla oleva koodi.",
- "embed.preview": "Tältä se tulee näyttämään:",
+ "confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta käyttäjää {name}?",
+ "embed.instructions": "Upota statuspäivitys sivullesi kopioimalla alla oleva koodi.",
+ "embed.preview": "Se tulee näyttämään tältä:",
"emoji_button.activity": "Aktiviteetit",
"emoji_button.custom": "Mukautetut",
"emoji_button.flags": "Liput",
@@ -92,154 +92,155 @@
"emoji_button.label": "Lisää emoji",
"emoji_button.nature": "Luonto",
"emoji_button.not_found": "Ei emojeja!! (╯°□°)╯︵ ┻━┻",
- "emoji_button.objects": "Objektit",
+ "emoji_button.objects": "Esineet",
"emoji_button.people": "Ihmiset",
"emoji_button.recent": "Usein käytetyt",
"emoji_button.search": "Etsi...",
"emoji_button.search_results": "Hakutulokset",
"emoji_button.symbols": "Symbolit",
"emoji_button.travel": "Matkailu",
- "empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista saadaksesi pyörät pyörimään!",
- "empty_column.hashtag": "Tässä hashtagissa ei ole vielä mitään.",
- "empty_column.home": "Kotiaikajanasi on tyhjä! Käy vierailemassa {public}ssa tai käytä hakutoimintoa aloittaaksesi ja tavataksesi muita käyttäjiä.",
+ "empty_column.community": "Paikallinen aikajana on tyhjä. Homma lähtee käyntiin, kun kirjoitat jotain julkista!",
+ "empty_column.hashtag": "Tällä hashtagilla ei ole vielä mitään.",
+ "empty_column.home": "Kotiaikajanasi on tyhjä! {public} ja hakutoiminto auttavat alkuun ja kohtaamaan muita käyttäjiä.",
"empty_column.home.public_timeline": "yleinen aikajana",
- "empty_column.list": "Tämä lista on vielä tyhjä. Kun listan jäsenet julkaisevat statuspäivityksiä, ne näkyvät tässä.",
- "empty_column.notifications": "Sinulle ei ole vielä ilmoituksia. Juttele muille aloittaaksesi keskustelun.",
- "empty_column.public": "Täällä ei ole mitään! Kirjoita jotain julkisesti, tai käy manuaalisesti seuraamassa käyttäjiä muista instansseista saadaksesi sisältöä",
+ "empty_column.list": "Lista on vielä tyhjä. Listan jäsenten julkaisemat tilapäivitykset tulevat tähän näkyviin.",
+ "empty_column.notifications": "Sinulle ei ole vielä ilmoituksia. Aloita keskustelu juttelemalla muille.",
+ "empty_column.public": "Täällä ei ole mitään! Saat sisältöä, kun kirjoitat jotain julkisesti tai käyt manuaalisesti seuraamassa muiden instanssien käyttäjiä",
"follow_request.authorize": "Valtuuta",
"follow_request.reject": "Hylkää",
"getting_started.appsshort": "Sovellukset",
"getting_started.faq": "FAQ",
"getting_started.heading": "Aloitus",
- "getting_started.open_source_notice": "Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}.",
+ "getting_started.open_source_notice": "Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHubissa: {github}.",
"getting_started.userguide": "Käyttöopas",
- "home.column_settings.advanced": "Tarkemmat asetukset",
+ "home.column_settings.advanced": "Lisäasetukset",
"home.column_settings.basic": "Perusasetukset",
- "home.column_settings.filter_regex": "Suodata säännöllisten lauseiden avulla",
+ "home.column_settings.filter_regex": "Suodata säännöllisillä lausekkeilla",
"home.column_settings.show_reblogs": "Näytä buustaukset",
"home.column_settings.show_replies": "Näytä vastaukset",
"home.settings": "Sarakeasetukset",
- "keyboard_shortcuts.back": "liikkuaksesi taaksepäin",
- "keyboard_shortcuts.boost": "buustataksesi",
- "keyboard_shortcuts.column": "keskittääksesi statuspäivitykseen yhdessä sarakkeista",
- "keyboard_shortcuts.compose": "aktivoidaksesi tekstinkirjoitusalueen",
- "keyboard_shortcuts.description": "Description",
- "keyboard_shortcuts.down": "liikkuaksesi listassa alaspäin",
- "keyboard_shortcuts.enter": "to open status",
- "keyboard_shortcuts.favourite": "tykätäksesi",
- "keyboard_shortcuts.heading": "Näppäinoikotiet",
+ "keyboard_shortcuts.back": "liiku taaksepäin",
+ "keyboard_shortcuts.boost": "buustaa",
+ "keyboard_shortcuts.column": "siirrä fokus tietyn sarakkeen tilapäivitykseen",
+ "keyboard_shortcuts.compose": "siirry tekstinsyöttöön",
+ "keyboard_shortcuts.description": "Kuvaus",
+ "keyboard_shortcuts.down": "siirry listassa alaspäin",
+ "keyboard_shortcuts.enter": "avaa tilapäivitys",
+ "keyboard_shortcuts.favourite": "tykkää",
+ "keyboard_shortcuts.heading": "Näppäinkomennot",
"keyboard_shortcuts.hotkey": "Pikanäppäin",
- "keyboard_shortcuts.legend": "näyttääksesi tämän selitteen",
- "keyboard_shortcuts.mention": "mainitaksesi julkaisijan",
- "keyboard_shortcuts.reply": "vastataksesi",
- "keyboard_shortcuts.search": "aktivoidaksesi hakukentän",
- "keyboard_shortcuts.toot": "aloittaaksesi uuden töötin kirjoittamisen",
- "keyboard_shortcuts.unfocus": "poistaaksesi aktivoinnin tekstikentästä/hakukentästä",
- "keyboard_shortcuts.up": "liikkuaksesi listassa ylöspäin",
+ "keyboard_shortcuts.legend": "näytä tämä selite",
+ "keyboard_shortcuts.mention": "mainitse julkaisija",
+ "keyboard_shortcuts.reply": "vastaa",
+ "keyboard_shortcuts.search": "siirry hakukenttään",
+ "keyboard_shortcuts.toot": "ala kirjoittaa uutta tuuttausta",
+ "keyboard_shortcuts.unfocus": "siirry pois tekstikentästä tai hakukentästä",
+ "keyboard_shortcuts.up": "siirry listassa ylöspäin",
"lightbox.close": "Sulje",
"lightbox.next": "Seuraava",
"lightbox.previous": "Edellinen",
"lists.account.add": "Lisää listaan",
- "lists.account.remove": "Poista listalta",
- "lists.delete": "Delete list",
+ "lists.account.remove": "Poista listasta",
+ "lists.delete": "Poista lista",
"lists.edit": "Muokkaa listaa",
"lists.new.create": "Lisää lista",
- "lists.new.title_placeholder": "Uuden listan otsikko",
- "lists.search": "Etsi seuraamiesi henkilöiden joukosta",
+ "lists.new.title_placeholder": "Uuden listan nimi",
+ "lists.search": "Etsi seuraamistasi henkilöistä",
"lists.subheading": "Omat listat",
"loading_indicator.label": "Ladataan...",
"media_gallery.toggle_visible": "Säädä näkyvyyttä",
- "missing_indicator.label": "Ei löydetty",
+ "missing_indicator.label": "Ei löytynyt",
"missing_indicator.sublabel": "Tätä resurssia ei löytynyt",
- "mute_modal.hide_notifications": "Piilota ilmoitukset tältä käyttäjältä?",
+ "mute_modal.hide_notifications": "Piilota tältä käyttäjältä tulevat ilmoitukset?",
"navigation_bar.blocks": "Estetyt käyttäjät",
"navigation_bar.community_timeline": "Paikallinen aikajana",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Muokkaa profiilia",
"navigation_bar.favourites": "Suosikit",
- "navigation_bar.follow_requests": "Seurauspyynnöt",
+ "navigation_bar.follow_requests": "Seuraamispyynnöt",
"navigation_bar.info": "Tietoa tästä instanssista",
- "navigation_bar.keyboard_shortcuts": "Näppäinoikotiet",
+ "navigation_bar.keyboard_shortcuts": "Näppäinkomennot",
"navigation_bar.lists": "Listat",
"navigation_bar.logout": "Kirjaudu ulos",
"navigation_bar.mutes": "Mykistetyt käyttäjät",
- "navigation_bar.pins": "Kiinnitetyt töötit",
- "navigation_bar.preferences": "Ominaisuudet",
+ "navigation_bar.pins": "Kiinnitetyt tuuttaukset",
+ "navigation_bar.preferences": "Asetukset",
"navigation_bar.public_timeline": "Yleinen aikajana",
- "notification.favourite": "{name} tykkäsi statuksestasi",
+ "notification.favourite": "{name} tykkäsi tilastasi",
"notification.follow": "{name} seurasi sinua",
"notification.mention": "{name} mainitsi sinut",
- "notification.reblog": "{name} buustasi statustasi",
+ "notification.reblog": "{name} buustasi tilaasi",
"notifications.clear": "Tyhjennä ilmoitukset",
- "notifications.clear_confirmation": "Oletko varma, että haluat lopullisesti tyhjentää kaikki ilmoituksesi?",
- "notifications.column_settings.alert": "Työpöytä ilmoitukset",
- "notifications.column_settings.favourite": "Tykkäyksiä:",
- "notifications.column_settings.follow": "Uusia seuraajia:",
- "notifications.column_settings.mention": "Mainintoja:",
+ "notifications.clear_confirmation": "Haluatko varmasti poistaa kaikki ilmoitukset pysyvästi?",
+ "notifications.column_settings.alert": "Työpöytäilmoitukset",
+ "notifications.column_settings.favourite": "Tykkäykset:",
+ "notifications.column_settings.follow": "Uudet seuraajat:",
+ "notifications.column_settings.mention": "Maininnat:",
"notifications.column_settings.push": "Push-ilmoitukset",
"notifications.column_settings.push_meta": "Tämä laite",
- "notifications.column_settings.reblog": "Buusteja:",
+ "notifications.column_settings.reblog": "Buustit:",
"notifications.column_settings.show": "Näytä sarakkeessa",
- "notifications.column_settings.sound": "Soita ääni",
+ "notifications.column_settings.sound": "Äänimerkki",
"onboarding.done": "Valmis",
"onboarding.next": "Seuraava",
- "onboarding.page_five.public_timelines": "Paikallinen aikajana näyttää kaikki julkiset julkaisut kaikilta, jotka ovat verkko-osoitteessa {domain}. Yleinen aikajana näyttää julkiset julkaisut kaikilta niiltä, joita käyttäjät verkko-osoitteessa {domain} seuraavat. Nämä ovat julkiset aikajanat, ja ne ovat hyviä tapoja löytää uusia ihmisiä.",
- "onboarding.page_four.home": "Kotiaikajana näyttää julkaisut ihmisiltä joita seuraat.",
- "onboarding.page_four.notifications": "Ilmoitukset-sarake näyttää sinulle, kun joku on viestii kanssasi.",
- "onboarding.page_one.federation": "Mastodon on yhteisöpalvelu, joka toimii monen itsenäisen palvelimen muodostamassa verkossa. Me kutsumme näitä palvelimia instansseiksi.",
+ "onboarding.page_five.public_timelines": "Paikallisella aikajanalla näytetään instanssin {domain} kaikkien käyttäjien julkiset julkaisut. Yleisellä aikajanalla näytetään kaikkien instanssin {domain} käyttäjien seuraamien käyttäjien julkiset julkaisut. Nämä julkiset aikajanat ovat loistavia paikkoja löytää uusia ihmisiä.",
+ "onboarding.page_four.home": "Kotiaikajanalla näytetään seuraamiesi ihmisten julkaisut.",
+ "onboarding.page_four.notifications": "Ilmoitukset-sarakkeessa näytetään muiden sinuun liittyvä toiminta.",
+ "onboarding.page_one.federation": "Mastodon on usean itsenäisen palvelimen muodostama yhteisöpalvelu. Näitä palvelimia kutsutaan instansseiksi.",
"onboarding.page_one.full_handle": "Koko käyttäjänimesi",
- "onboarding.page_one.handle_hint": "Tämä on se, mitä voisit ehdottaa ystäviäsi etsimään.",
+ "onboarding.page_one.handle_hint": "Tällä nimellä ystäväsi löytävät sinut.",
"onboarding.page_one.welcome": "Tervetuloa Mastodoniin!",
- "onboarding.page_six.admin": "Instanssisi ylläpitäjä on {admin}.",
+ "onboarding.page_six.admin": "Instanssin ylläpitäjä on {admin}.",
"onboarding.page_six.almost_done": "Melkein valmista...",
- "onboarding.page_six.appetoot": "Bon Appetööt!",
+ "onboarding.page_six.appetoot": "Tuuttailun iloa!",
"onboarding.page_six.apps_available": "{apps} on saatavilla iOS:lle, Androidille ja muille alustoille.",
- "onboarding.page_six.github": "Mastodon on ilmainen, vapaan lähdekoodin ohjelma. Voit raportoida bugeja, pyytää ominaisuuksia tai osallistua kehittämiseen GitHub-palvelussa: {github}.",
+ "onboarding.page_six.github": "Mastodon on ilmainen, vapaan lähdekoodin ohjelma. Voit raportoida bugeja, ehdottaa ominaisuuksia tai osallistua kehittämiseen GitHubissa: {github}.",
"onboarding.page_six.guidelines": "yhteisön säännöt",
"onboarding.page_six.read_guidelines": "Ole hyvä ja lue {domain}:n {guidelines}!",
"onboarding.page_six.various_app": "mobiilisovellukset",
- "onboarding.page_three.profile": "Muokkaa profiiliasi muuttaaksesi kuvakettasi, esittelyäsi ja nimimerkkiäsi. Löydät sieltä myös muita henkilökohtaisia asetuksia.",
- "onboarding.page_three.search": "Käytä hakukenttää löytääksesi ihmisiä ja etsiäksesi hashtageja, kuten {illustration} tai {introductions}. Hakeaksesi henkilöä joka on toisessa instanssissa, käytä hänen käyttäjänimeään kokonaisuudessaan.",
- "onboarding.page_two.compose": "Kirjoita postauksia kirjoita-sarakkeessa. Voit ladata kuvia, vaihtaa yksityisyysasetuksia ja lisätä sisältövaroituksia alla olevista painikkeista.",
+ "onboarding.page_three.profile": "Voit muuttaa profiilikuvaasi, esittelyäsi ja nimimerkkiäsi sekä muita asetuksia muokkaamalla profiiliasi.",
+ "onboarding.page_three.search": "Etsi ihmisiä ja hashtageja (esimerkiksi {illustration} tai {introductions}) hakukentän avulla. Jos haet toista instanssia käyttävää henkilöä, käytä hänen koko käyttäjänimeään.",
+ "onboarding.page_two.compose": "Kirjoita julkaisuja kirjoitussarakkeessa. Voit ladata kuvia, vaihtaa näkyvyysasetuksia ja lisätä sisältövaroituksia alla olevista painikkeista.",
"onboarding.skip": "Ohita",
- "privacy.change": "Säädä töötin yksityisyysasetuksia",
+ "privacy.change": "Säädä tuuttauksen näkyvyyttä",
"privacy.direct.long": "Julkaise vain mainituille käyttäjille",
- "privacy.direct.short": "Yksityisviesti",
+ "privacy.direct.short": "Suora viesti",
"privacy.private.long": "Julkaise vain seuraajille",
"privacy.private.short": "Vain seuraajat",
"privacy.public.long": "Julkaise julkisille aikajanoille",
"privacy.public.short": "Julkinen",
- "privacy.unlisted.long": "Älä julkaise yleisillä aikajanoilla",
- "privacy.unlisted.short": "Julkinen, mutta älä näytä julkisella aikajanalla",
+ "privacy.unlisted.long": "Älä julkaise julkisilla aikajanoilla",
+ "privacy.unlisted.short": "Listaamaton julkinen",
"regeneration_indicator.label": "Ladataan…",
"regeneration_indicator.sublabel": "Kotinäkymääsi valmistellaan!",
- "relative_time.days": "{number}d",
- "relative_time.hours": "{number}h",
+ "relative_time.days": "{number} pv",
+ "relative_time.hours": "{number} h",
"relative_time.just_now": "nyt",
- "relative_time.minutes": "{number}m",
- "relative_time.seconds": "{number}s",
+ "relative_time.minutes": "{number} m",
+ "relative_time.seconds": "{number} s",
"reply_indicator.cancel": "Peruuta",
- "report.forward": "Uudelleenohjaa kohteeseen {target}",
- "report.forward_hint": "Tämä tili on toiselta serveriltä. Haluatko, että myös sinne lähetetään anonymisoitu kopio ilmiantoraportista?",
- "report.hint": "Ilmianto lähetetään instanssisi moderaattoreille. Voit antaa kuvauksen käyttäjän ilmiantamisen syystä alle:",
+ "report.forward": "Välitä kohteeseen {target}",
+ "report.forward_hint": "Tämä tili on toisella palvelimella. Haluatko lähettää nimettömän raportin myös sinne?",
+ "report.hint": "Raportti lähetetään oman instanssisi moderaattoreille. Seuraavassa voit kertoa, miksi raportoit tästä tilistä:",
"report.placeholder": "Lisäkommentit",
- "report.submit": "Submit",
- "report.target": "Reporting",
+ "report.submit": "Lähetä",
+ "report.target": "Raportoidaan {target}",
"search.placeholder": "Hae",
"search_popout.search_format": "Tarkennettu haku",
- "search_popout.tips.full_text": "Tekstihaku palauttaa statuspäivitykset jotka olet kirjoittanut, lisännyt suosikkeihisi, boostannut tai joissa sinut mainitaan, sekä käyttäjänimet, nimimerkit ja hastagit jotka sisältävät tekstin.",
- "search_popout.tips.hashtag": "hashtagi",
- "search_popout.tips.status": "status",
- "search_popout.tips.text": "Pelkkä tekstihaku palauttaa hakua vastaavat nimimerkit, käyttäjänimet ja hastagit",
+ "search_popout.tips.full_text": "Tekstihaku palauttaa tilapäivitykset, jotka olet kirjoittanut, lisännyt suosikkeihisi, boostannut tai joissa sinut mainitaan, sekä tekstin sisältävät käyttäjänimet, nimimerkit ja hastagit.",
+ "search_popout.tips.hashtag": "hashtag",
+ "search_popout.tips.status": "tila",
+ "search_popout.tips.text": "Tekstihaku palauttaa hakua vastaavat nimimerkit, käyttäjänimet ja hastagit",
"search_popout.tips.user": "käyttäjä",
"search_results.accounts": "Ihmiset",
"search_results.hashtags": "Hashtagit",
- "search_results.statuses": "Töötit",
+ "search_results.statuses": "Tuuttaukset",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "Kurkistus sisälle...",
- "status.block": "Block @{name}",
- "status.cannot_reblog": "Tätä postausta ei voi buustata",
+ "status.block": "Estä @{name}",
+ "status.cannot_reblog": "Tätä julkaisua ei voi buustata",
"status.delete": "Poista",
+ "status.direct": "Direct message @{name}",
"status.embed": "Upota",
"status.favourite": "Tykkää",
"status.load_more": "Lataa lisää",
@@ -248,29 +249,30 @@
"status.more": "Lisää",
"status.mute": "Mykistä @{name}",
"status.mute_conversation": "Mykistä keskustelu",
- "status.open": "Laajenna statuspäivitys",
+ "status.open": "Laajenna tilapäivitys",
"status.pin": "Kiinnitä profiiliin",
- "status.pinned": "Kiinnitetty töötti",
+ "status.pinned": "Kiinnitetty tuuttaus",
"status.reblog": "Buustaa",
"status.reblogged_by": "{name} buustasi",
"status.reply": "Vastaa",
"status.replyAll": "Vastaa ketjuun",
- "status.report": "Report @{name}",
+ "status.report": "Raportoi @{name}",
"status.sensitive_toggle": "Klikkaa nähdäksesi",
"status.sensitive_warning": "Arkaluontoista sisältöä",
"status.share": "Jaa",
"status.show_less": "Näytä vähemmän",
"status.show_less_all": "Näytä vähemmän kaikista",
"status.show_more": "Näytä lisää",
- "status.show_more_all": "Näytä enemmän kaikista",
- "status.unmute_conversation": "Poista mykistys keskustelulta",
+ "status.show_more_all": "Näytä lisää kaikista",
+ "status.unmute_conversation": "Poista keskustelun mykistys",
"status.unpin": "Irrota profiilista",
"tabs_bar.federated_timeline": "Yleinen",
"tabs_bar.home": "Koti",
"tabs_bar.local_timeline": "Paikallinen",
"tabs_bar.notifications": "Ilmoitukset",
- "ui.beforeunload": "Luonnoksesi menetetään, jos poistut Mastodonista.",
- "upload_area.title": "Raahaa ja pudota tähän ladataksesi",
+ "tabs_bar.search": "Search",
+ "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.",
+ "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
"upload_button.label": "Lisää mediaa",
"upload_form.description": "Anna kuvaus näkörajoitteisia varten",
"upload_form.focus": "Rajaa",
@@ -279,10 +281,10 @@
"video.close": "Sulje video",
"video.exit_fullscreen": "Poistu koko näytön tilasta",
"video.expand": "Laajenna video",
- "video.fullscreen": "Full screen",
+ "video.fullscreen": "Koko näyttö",
"video.hide": "Piilota video",
"video.mute": "Mykistä ääni",
"video.pause": "Keskeytä",
"video.play": "Toista",
- "video.unmute": "Poista mykistys ääneltä"
+ "video.unmute": "Poista äänen mykistys"
}
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 57c55c9bd..e340fda9e 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Cette publication ne peut être boostée",
"status.delete": "Effacer",
+ "status.direct": "Direct message @{name}",
"status.embed": "Intégrer",
"status.favourite": "Ajouter aux favoris",
"status.load_more": "Charger plus",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Accueil",
"tabs_bar.local_timeline": "Fil public local",
"tabs_bar.notifications": "Notifications",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
"upload_area.title": "Glissez et déposez pour envoyer",
"upload_button.label": "Joindre un média",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 8d586404d..5cbb7d31d 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -2,7 +2,7 @@
"account.block": "Bloquear @{name}",
"account.block_domain": "Ocultar calquer contido de {domain}",
"account.blocked": "Blocked",
- "account.direct": "Direct Message @{name}",
+ "account.direct": "Direct message @{name}",
"account.disclaimer_full": "A información inferior podería mostrar un perfil incompleto da usuaria.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Editar perfil",
@@ -148,7 +148,7 @@
"lists.search": "Procurar entre a xente que segues",
"lists.subheading": "As túas listas",
"loading_indicator.label": "Cargando...",
- "media_gallery.toggle_visible": "Dar visibilidade",
+ "media_gallery.toggle_visible": "Ocultar",
"missing_indicator.label": "Non atopado",
"missing_indicator.sublabel": "This resource could not be found",
"mute_modal.hide_notifications": "Esconder notificacións deste usuario?",
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Esta mensaxe non pode ser promocionada",
"status.delete": "Eliminar",
+ "status.direct": "Direct message @{name}",
"status.embed": "Incrustar",
"status.favourite": "Favorita",
"status.load_more": "Cargar máis",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Inicio",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificacións",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "O borrador perderase se sae de Mastodon.",
"upload_area.title": "Arrastre e solte para subir",
"upload_button.label": "Engadir medios",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 6bec26fd8..656d93cdf 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "לא ניתן להדהד הודעה זו",
"status.delete": "מחיקה",
+ "status.direct": "Direct message @{name}",
"status.embed": "הטמעה",
"status.favourite": "חיבוב",
"status.load_more": "עוד",
@@ -269,6 +270,7 @@
"tabs_bar.home": "בבית",
"tabs_bar.local_timeline": "ציר זמן מקומי",
"tabs_bar.notifications": "התראות",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.",
"upload_area.title": "ניתן להעלות על ידי Drag & drop",
"upload_button.label": "הוספת מדיה",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index f7a5d0a3f..2d7d0a5a4 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Ovaj post ne može biti boostan",
"status.delete": "Obriši",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Označi omiljenim",
"status.load_more": "Učitaj više",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Dom",
"tabs_bar.local_timeline": "Lokalno",
"tabs_bar.notifications": "Notifikacije",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Povuci i spusti kako bi uploadao",
"upload_button.label": "Dodaj media",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 8b9c14993..24f3a7816 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Ezen státusz nem rebloggolható",
"status.delete": "Törlés",
+ "status.direct": "Direct message @{name}",
"status.embed": "Beágyaz",
"status.favourite": "Kedvenc",
"status.load_more": "Többet",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Kezdőlap",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Értesítések",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "A piszkozata el fog vesztődni ha elhagyja Mastodon-t.",
"upload_area.title": "Húzza ide a feltöltéshez",
"upload_button.label": "Média hozzáadása",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 22ba89a43..2ba52c5c0 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -240,6 +240,7 @@
"status.block": "Արգելափակել @{name}֊ին",
"status.cannot_reblog": "Այս թութը չի կարող տարածվել",
"status.delete": "Ջնջել",
+ "status.direct": "Direct message @{name}",
"status.embed": "Ներդնել",
"status.favourite": "Հավանել",
"status.load_more": "Բեռնել ավելին",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Հիմնական",
"tabs_bar.local_timeline": "Տեղական",
"tabs_bar.notifications": "Ծանուցումներ",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։",
"upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
"upload_button.label": "Ավելացնել մեդիա",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index 1ef610fba..e1518c1aa 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Hapus",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Difavoritkan",
"status.load_more": "Tampilkan semua",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Beranda",
"tabs_bar.local_timeline": "Lokal",
"tabs_bar.notifications": "Notifikasi",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Naskah anda akan hilang jika anda keluar dari Mastodon.",
"upload_area.title": "Seret & lepaskan untuk mengunggah",
"upload_button.label": "Tambahkan media",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index 1435178a8..c79d4a634 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Efacar",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Favorizar",
"status.load_more": "Kargar pluse",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Hemo",
"tabs_bar.local_timeline": "Lokala",
"tabs_bar.notifications": "Savigi",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Tranar faligar por kargar",
"upload_button.label": "Adjuntar kontenajo",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 226127e6b..3c85a3e20 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Elimina",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Apprezzato",
"status.load_more": "Mostra di più",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Locale",
"tabs_bar.notifications": "Notifiche",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Trascina per caricare",
"upload_button.label": "Aggiungi file multimediale",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index a9beaa335..2da9192ca 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -186,7 +186,7 @@
"onboarding.page_five.public_timelines": "連合タイムラインでは{domain}の人がフォローしているMastodon全体での公開投稿を表示します。同じくローカルタイムラインでは{domain}のみの公開投稿を表示します。",
"onboarding.page_four.home": "「ホーム」タイムラインではあなたがフォローしている人の投稿を表示します。",
"onboarding.page_four.notifications": "「通知」ではあなたへの他の人からの関わりを表示します。",
- "onboarding.page_one.federation": "Mastodonは誰でも参加できるSNSです。",
+ "onboarding.page_one.federation": "Mastodonは独立したインスタンス(サーバー)の集合体です。",
"onboarding.page_one.full_handle": "あなたのフルハンドル",
"onboarding.page_one.handle_hint": "あなたを探している友達に伝えるといいでしょう。",
"onboarding.page_one.welcome": "Mastodonへようこそ!",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 89fde8966..e2fadff3c 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -240,6 +240,7 @@
"status.block": "@{name} 차단",
"status.cannot_reblog": "이 포스트는 부스트 할 수 없습니다",
"status.delete": "삭제",
+ "status.direct": "Direct message @{name}",
"status.embed": "공유하기",
"status.favourite": "즐겨찾기",
"status.load_more": "더 보기",
@@ -269,6 +270,7 @@
"tabs_bar.home": "홈",
"tabs_bar.local_timeline": "로컬",
"tabs_bar.notifications": "알림",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.",
"upload_area.title": "드래그 & 드롭으로 업로드",
"upload_button.label": "미디어 추가",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 7bfb74a5c..0222432a0 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -240,6 +240,7 @@
"status.block": "Blokkeer @{name}",
"status.cannot_reblog": "Deze toot kan niet geboost worden",
"status.delete": "Verwijderen",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Favoriet",
"status.load_more": "Meer laden",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Start",
"tabs_bar.local_timeline": "Lokaal",
"tabs_bar.notifications": "Meldingen",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.",
"upload_area.title": "Hierin slepen om te uploaden",
"upload_button.label": "Media toevoegen",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index b79277ce3..20b2cbb26 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Denne posten kan ikke fremheves",
"status.delete": "Slett",
+ "status.direct": "Direct message @{name}",
"status.embed": "Bygge inn",
"status.favourite": "Lik",
"status.load_more": "Last mer",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Hjem",
"tabs_bar.local_timeline": "Lokal",
"tabs_bar.notifications": "Varslinger",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Din kladd vil bli forkastet om du forlater Mastodon.",
"upload_area.title": "Dra og slipp for å laste opp",
"upload_button.label": "Legg til media",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 5b12f8811..32133c1f4 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -240,6 +240,7 @@
"status.block": "Blocar @{name}",
"status.cannot_reblog": "Aqueste estatut pòt pas èsser partejat",
"status.delete": "Escafar",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embarcar",
"status.favourite": "Apondre als favorits",
"status.load_more": "Cargar mai",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Acuèlh",
"tabs_bar.local_timeline": "Flux public local",
"tabs_bar.notifications": "Notificacions",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Vòstre brolhon serà perdut se quitatz Mastodon.",
"upload_area.title": "Lisatz e depausatz per mandar",
"upload_button.label": "Ajustar un mèdia",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index 4cd2e0643..b4be0bbc7 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Esta postagem não pode ser compartilhada",
"status.delete": "Excluir",
+ "status.direct": "Direct message @{name}",
"status.embed": "Incorporar",
"status.favourite": "Adicionar aos favoritos",
"status.load_more": "Carregar mais",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Página inicial",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificações",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar mídia",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index 7a404eaba..132de5293 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Este post não pode ser partilhado",
"status.delete": "Eliminar",
+ "status.direct": "Direct message @{name}",
"status.embed": "Incorporar",
"status.favourite": "Adicionar aos favoritos",
"status.load_more": "Carregar mais",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificações",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "O teu rascunho vai ser perdido se abandonares o Mastodon.",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar media",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index 8616ef98f..b56ccf1df 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -240,6 +240,7 @@
"status.block": "Заблокировать @{name}",
"status.cannot_reblog": "Этот статус не может быть продвинут",
"status.delete": "Удалить",
+ "status.direct": "Direct message @{name}",
"status.embed": "Встроить",
"status.favourite": "Нравится",
"status.load_more": "Показать еще",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Главная",
"tabs_bar.local_timeline": "Локальная",
"tabs_bar.notifications": "Уведомления",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.",
"upload_area.title": "Перетащите сюда, чтобы загрузить",
"upload_button.label": "Добавить медиаконтент",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 925b46df6..159315137 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -8,11 +8,11 @@
"account.edit_profile": "Upraviť profil",
"account.follow": "Následovať",
"account.followers": "Sledujúci",
- "account.follows": "Sledujete",
+ "account.follows": "Následuje",
"account.follows_you": "Následuje ťa",
"account.hide_reblogs": "Skryť povýšenia od @{name}",
"account.media": "Médiá",
- "account.mention": "Spomeňte @{name}",
+ "account.mention": "Spomeň @{name}",
"account.moved_to": "{name} sa presunul/a na:",
"account.mute": "Ignorovať @{name}",
"account.mute_notifications": "Stĺmiť notifikácie od @{name}",
@@ -22,7 +22,7 @@
"account.report": "Nahlás @{name}",
"account.requested": "Čaká na schválenie. Kliknite pre zrušenie žiadosti",
"account.share": "Zdieľať @{name} profil",
- "account.show_reblogs": "Zobraziť povýšenia od @{name}",
+ "account.show_reblogs": "Ukáž povýšenia od @{name}",
"account.unblock": "Odblokovať @{name}",
"account.unblock_domain": "Prestať blokovať {domain}",
"account.unfollow": "Prestať nasledovať",
@@ -83,7 +83,7 @@
"confirmations.mute.message": "Naozaj chcete ignorovať {name}?",
"confirmations.unfollow.confirm": "Nesledovať",
"confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?",
- "embed.instructions": "Umiestnite kód uvedený nižšie pre pridanie tohto statusu na vašu web stránku.",
+ "embed.instructions": "Umiestni kód uvedený nižšie pre pridanie tohto statusu na tvoju web stránku.",
"embed.preview": "Tu je ako to bude vyzerať:",
"emoji_button.activity": "Aktivita",
"emoji_button.custom": "Vlastné",
@@ -111,13 +111,13 @@
"getting_started.appsshort": "Aplikácie",
"getting_started.faq": "Časté otázky",
"getting_started.heading": "Začni tu",
- "getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispievať vlastným kódom môžete na GitHube v {github}.",
+ "getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispieť môžeš na GitHube v {github}.",
"getting_started.userguide": "Používateľská príručka",
"home.column_settings.advanced": "Pokročilé",
"home.column_settings.basic": "Základné",
"home.column_settings.filter_regex": "Filtrovať použitím regulárnych výrazov",
"home.column_settings.show_reblogs": "Zobraziť povýšené",
- "home.column_settings.show_replies": "Zobraziť odpovede",
+ "home.column_settings.show_replies": "Ukázať odpovede",
"home.settings": "Nastavenia stĺpcov",
"keyboard_shortcuts.back": "dostať sa naspäť",
"keyboard_shortcuts.boost": "vyzdvihnúť",
@@ -169,7 +169,7 @@
"notification.favourite": "{name} sa páči tvoj status",
"notification.follow": "{name} ťa začal/a následovať",
"notification.mention": "{name} ťa spomenul/a",
- "notification.reblog": "{name} re-tootol tvoj status",
+ "notification.reblog": "{name} zdieľal/a tvoj status",
"notifications.clear": "Vyčistiť zoznam notifikácii",
"notifications.clear_confirmation": "Naozaj chcete nenávratne prečistiť všetky vaše notifikácie?",
"notifications.column_settings.alert": "Notifikácie na ploche",
@@ -235,24 +235,25 @@
"search_results.accounts": "Ľudia",
"search_results.hashtags": "Haštagy",
"search_results.statuses": "Príspevky",
- "search_results.total": "{count, number} {count, plural, one {result} ostatné {results}}",
- "standalone.public_title": "Pohľad dovnútra...",
+ "search_results.total": "{count, number} {count, plural, jeden {výsledok} ostatné {výsledky}}",
+ "standalone.public_title": "Náhľad dovnútra...",
"status.block": "Blokovať @{name}",
"status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
"status.delete": "Zmazať",
+ "status.direct": "Direct message @{name}",
"status.embed": "Vložiť",
"status.favourite": "Páči sa mi",
"status.load_more": "Zobraz viac",
"status.media_hidden": "Skryté médiá",
- "status.mention": "Napísať @{name}",
+ "status.mention": "Spomeň @{name}",
"status.more": "Viac",
"status.mute": "Utíšiť @{name}",
"status.mute_conversation": "Ignorovať konverzáciu",
"status.open": "Otvoriť tento status",
- "status.pin": "Pripnúť na profil",
+ "status.pin": "Pripni na profil",
"status.pinned": "Pripnutý príspevok",
"status.reblog": "Povýšiť",
- "status.reblogged_by": "{name} povýšil",
+ "status.reblogged_by": "{name} povýšil/a",
"status.reply": "Odpovedať",
"status.replyAll": "Odpovedať na diskusiu",
"status.report": "Nahlásiť @{name}",
@@ -261,7 +262,7 @@
"status.share": "Zdieľať",
"status.show_less": "Zobraz menej",
"status.show_less_all": "Všetkým ukáž menej",
- "status.show_more": "Zobraz viac",
+ "status.show_more": "Zobraziť viac",
"status.show_more_all": "Všetkým ukáž viac",
"status.unmute_conversation": "Prestať ignorovať konverzáciu",
"status.unpin": "Odopnúť z profilu",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Domov",
"tabs_bar.local_timeline": "Lokálna",
"tabs_bar.notifications": "Notifikácie",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Čo máte rozpísané sa stratí, ak opustíte Mastodon.",
"upload_area.title": "Ťahaj a pusti pre nahratie",
"upload_button.label": "Pridať médiá",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index 8fae49a03..69c7aa62b 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Ovaj status ne može da se podrži",
"status.delete": "Obriši",
+ "status.direct": "Direct message @{name}",
"status.embed": "Ugradi na sajt",
"status.favourite": "Omiljeno",
"status.load_more": "Učitaj još",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Početna",
"tabs_bar.local_timeline": "Lokalno",
"tabs_bar.notifications": "Obaveštenja",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Ako napustite Mastodont, izgubićete napisani nacrt.",
"upload_area.title": "Prevucite ovde da otpremite",
"upload_button.label": "Dodaj multimediju",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index a39fea582..e9739451e 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Овај статус не може да се подржи",
"status.delete": "Обриши",
+ "status.direct": "Direct message @{name}",
"status.embed": "Угради на сајт",
"status.favourite": "Омиљено",
"status.load_more": "Учитај још",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Почетна",
"tabs_bar.local_timeline": "Локално",
"tabs_bar.notifications": "Обавештења",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Ако напустите Мастодонт, изгубићете написани нацрт.",
"upload_area.title": "Превуците овде да отпремите",
"upload_button.label": "Додај мултимедију",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 014492e19..b063adb0f 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Detta inlägg kan inte knuffas",
"status.delete": "Ta bort",
+ "status.direct": "Direct message @{name}",
"status.embed": "Bädda in",
"status.favourite": "Favorit",
"status.load_more": "Ladda fler",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Hem",
"tabs_bar.local_timeline": "Lokal",
"tabs_bar.notifications": "Meddelanden",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Ditt utkast kommer att förloras om du lämnar Mastodon.",
"upload_area.title": "Dra & släpp för att ladda upp",
"upload_button.label": "Lägg till media",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index ecfe7c9b5..22a75c237 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Delete",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Favourite",
"status.load_more": "Load more",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notifications",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 58d0e5785..8e36c512f 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Bu gönderi boost edilemez",
"status.delete": "Sil",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Favorilere ekle",
"status.load_more": "Daha fazla",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Ana sayfa",
"tabs_bar.local_timeline": "Yerel",
"tabs_bar.notifications": "Bildirimler",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Upload için sürükle bırak yapınız",
"upload_button.label": "Görsel ekle",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 63866d339..09210a325 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -240,6 +240,7 @@
"status.block": "Block @{name}",
"status.cannot_reblog": "Цей допис не може бути передмухнутий",
"status.delete": "Видалити",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "Подобається",
"status.load_more": "Завантажити більше",
@@ -269,6 +270,7 @@
"tabs_bar.home": "Головна",
"tabs_bar.local_timeline": "Локальна",
"tabs_bar.notifications": "Сповіщення",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Перетягніть сюди, щоб завантажити",
"upload_button.label": "Додати медіаконтент",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index f7cb49632..f0772ffaa 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -240,6 +240,7 @@
"status.block": "屏蔽 @{name}",
"status.cannot_reblog": "无法转嘟这条嘟文",
"status.delete": "删除",
+ "status.direct": "Direct message @{name}",
"status.embed": "嵌入",
"status.favourite": "收藏",
"status.load_more": "加载更多",
@@ -269,6 +270,7 @@
"tabs_bar.home": "主页",
"tabs_bar.local_timeline": "本站",
"tabs_bar.notifications": "通知",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "如果你现在离开 Mastodon,你的草稿内容将会被丢弃。",
"upload_area.title": "将文件拖放到此处开始上传",
"upload_button.label": "上传媒体文件",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 1cbc9f1c5..bebb33e57 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -240,6 +240,7 @@
"status.block": "封鎖 @{name}",
"status.cannot_reblog": "這篇文章無法被轉推",
"status.delete": "刪除",
+ "status.direct": "Direct message @{name}",
"status.embed": "鑲嵌",
"status.favourite": "收藏",
"status.load_more": "載入更多",
@@ -269,6 +270,7 @@
"tabs_bar.home": "主頁",
"tabs_bar.local_timeline": "本站",
"tabs_bar.notifications": "通知",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "如果你現在離開 Mastodon,你的草稿內容將會被丟棄。",
"upload_area.title": "將檔案拖放至此上載",
"upload_button.label": "上載媒體檔案",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 3edb3fa50..efed9cd4d 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -240,6 +240,7 @@
"status.block": "封鎖 @{name}",
"status.cannot_reblog": "此貼文無法轉推",
"status.delete": "刪除",
+ "status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.favourite": "收藏",
"status.load_more": "載入更多",
@@ -269,6 +270,7 @@
"tabs_bar.home": "家",
"tabs_bar.local_timeline": "本地",
"tabs_bar.notifications": "通知",
+ "tabs_bar.search": "Search",
"ui.beforeunload": "如果離開 Mastodon,你的草稿將會不見。",
"upload_area.title": "拖放來上傳",
"upload_button.label": "增加媒體",
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index c316a2fa5..8b9a6688a 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -204,6 +204,7 @@ ar:
severity: الشدة
show:
affected_accounts:
+ one: هناك حساب واحد متأثر في قاعدة البيانات
other: هناك %{count} حسابات في قاعدة البيانات متأثرة بذلك
retroactive:
silence: إلغاء الكتم عن كافة الحسابات المتواجدة على هذا النطاق
@@ -262,6 +263,7 @@ ar:
settings:
activity_api_enabled:
desc_html: عدد المنشورات المحلية و المستخدمين النشطين و التسجيلات الأسبوعية الجديدة
+ title: نشر مُجمل الإحصائيات عن نشاط المستخدمين
bootstrap_timeline_accounts:
title: الإشتراكات الإفتراضية للمستخدمين الجدد
contact_information:
@@ -274,12 +276,14 @@ ar:
title: نشر عدد مثيلات الخوادم التي تم مصادفتها
registrations:
closed_message:
+ desc_html: يتم عرضه على الصفحة الرئيسية عندما يتم غلق تسجيل الحسابات الجديدة. يمكنكم إستخدام علامات الأيتش تي أم أل HTML
title: رسالة التسجيلات المقفلة
deletion:
desc_html: السماح لأي مستخدم إغلاق حسابه
title: السماح بحذف الحسابات
min_invite_role:
disabled: لا أحد
+ title: المستخدِمون المصرح لهم لإرسال الدعوات
open:
desc_html: السماح للجميع بإنشاء حساب
title: فتح التسجيل
diff --git a/config/locales/devise.fi.yml b/config/locales/devise.fi.yml
index 91ab9559c..e356abf9f 100644
--- a/config/locales/devise.fi.yml
+++ b/config/locales/devise.fi.yml
@@ -2,60 +2,81 @@
fi:
devise:
confirmations:
- confirmed: Sähköpostisi on onnistuneesti vahvistettu.
- send_instructions: Saat kohta sähköpostiisi ohjeet kuinka voit aktivoida tilisi.
- send_paranoid_instructions: Jos sähköpostisi on meidän tietokannassa, saat pian ohjeet sen varmentamiseen.
+ confirmed: Sähköpostiosoitteen vahvistus onnistui.
+ send_instructions: Saat kohta sähköpostitse ohjeet, kuinka vahvistat sähköpostiosoitteen. Jos et saa viestiä, tarkista roskapostikansio.
+ send_paranoid_instructions: Jos sähköpostiosoite on tietokannassamme, saat pian ohjeet, kuinka vahvistat osoitteen. Jos et saa viestiä, tarkista roskapostikansio.
failure:
already_authenticated: Olet jo kirjautunut sisään.
- inactive: Tiliäsi ei ole viellä aktivoitu.
+ inactive: Tiliäsi ei ole vielä aktivoitu.
invalid: Virheellinen %{authentication_keys} tai salasana.
- last_attempt: Sinulla on yksi yritys jäljellä tai tili lukitaan.
+ last_attempt: Voit yrittää enää kerran, ennen kuin tili lukitaan.
locked: Tili on lukittu.
not_found_in_database: Virheellinen %{authentication_keys} tai salasana.
- timeout: Sessiosi on umpeutunut. Kirjaudu sisään jatkaaksesi.
- unauthenticated: Sinun tarvitsee kirjautua sisään tai rekisteröityä jatkaaksesi.
- unconfirmed: Sinun tarvitsee varmentaa sähköpostisi jatkaaksesi.
+ timeout: Istunto on umpeutunut. Jatka kirjautumalla sisään.
+ unauthenticated: Kirjaudu sisään tai rekisteröidy, jos haluat jatkaa.
+ unconfirmed: Vahvista sähköpostiosoitteesi, ennen kuin jatkat.
mailer:
confirmation_instructions:
- subject: 'Mastodon: Varmistus ohjeet'
+ action: Vahvista sähköpostiosoite
+ explanation: Olet luonut tilin palvelimelle %{host} käyttäen tätä sähköpostiosoitetta. Aktivoi tili yhdellä klikkauksella. Jos et luonut tiliä itse, voit jättää tämän viestin huomiotta.
+ extra_html: Katso myös instanssin säännöt ja käyttöehdot.
+ subject: 'Mastodon: Vahvistusohjeet - %{instance}'
+ title: Vahvista sähköpostiosoite
+ email_changed:
+ explanation: 'Tilin sähköpostiosoitteeksi vaihdetaan:'
+ extra: Jos et vaihtanut sähköpostiosoitettasi, joku muu on todennäköisesti päässyt käyttämään tiliäsi. Vaihda salasanasi viipymättä. Jos et pääse kirjautumaan tilillesi, ota yhteyttä instanssin ylläpitäjään.
+ subject: 'Mastodon: Sähköpostiosoite vaihdettu'
+ title: Uusi sähköpostiosoite
password_change:
+ explanation: Tilin salasana on vaihdettu.
+ extra: Jos et vaihtanut salasanaasi, joku muu on todennäköisesti päässyt käyttämään tiliäsi. Vaihda salasanasi viipymättä. Jos et pääse kirjautumaan tilillesi, ota yhteyttä instanssin ylläpitäjään.
subject: 'Mastodon: Salasana vaihdettu'
+ title: Salasana vaihdettu
+ reconfirmation_instructions:
+ explanation: Vahvista uusi sähköpostiosoite, niin muutos astuu voimaan.
+ extra: Jos et tehnyt muutosta itse, voit jättää tämän viestin huomiotta. Mastodon-tilin sähköpostiosoitetta ei vaihdeta, ennen kuin klikkaat yllä olevaa linkkiä.
+ subject: 'Mastodon: Vahvista sähköpostiosoite - %{instance}'
+ title: Vahvista sähköpostiosoite
reset_password_instructions:
- subject: 'Mastodon: Salasanan vaihto ohjeet'
+ action: Vaihda salasana
+ explanation: Pyysit tilillesi uuden salasanan.
+ extra: Jos et tehnyt pyyntöä itse, voit jättää tämän viestin huomiotta. Salasanaasi ei vaihdeta, ennen kuin klikkaat yllä olevaa linkkiä ja luot uuden salasanan.
+ subject: 'Mastodon: Ohjeet salasanan vaihtoon'
+ title: Salasanan vaihto
unlock_instructions:
- subject: 'Mastodon: Avauksen ohjeet'
+ subject: 'Mastodon: Ohjeet lukituksen poistoon'
omniauth_callbacks:
- failure: Varmennus %{kind} epäonnistui koska "%{reason}".
- success: Onnistuneesti varmennettu %{kind} tilillä.
+ failure: Tunnistautuminen lähteestä %{kind} ei onnistunut, koska "%{reason}".
+ success: Tunnistautuminen tililtä %{kind} onnistui.
passwords:
- no_token: Et pääse tälle sivulle ilman salasanan vaihto sähköpostia. Jos tulet tämmöisestä postista, varmista että sinulla on täydellinen URL.
- send_instructions: Jos sähköpostisi on meidän tietokannassa, saat pian ohjeet salasanan palautukseen.
- send_paranoid_instructions: Jos sähköpostisi on meidän tietokannassa, saat pian ohjeet salasanan palautukseen.
- updated: Salasanasi vaihdettu onnistuneesti. Olet nyt kirjautunut sisään.
- updated_not_active: Salasanasi vaihdettu onnistuneesti.
+ no_token: Tälle sivulle pääsee vain salasananvaihtoviestin kautta. Jos tiedät tulevasi salasananvaihtoviestin kautta, varmista, että käytät koko viestissä mainittua URL-osoitetta.
+ send_instructions: Jos sähköpostiosoite on tietokannassamme, siihen lähetetään pian linkki salasanan vaihtoon. Jos et saa viestiä, tarkista roskapostikansio.
+ send_paranoid_instructions: Jos sähköpostiosoite on tietokannassamme, siihen lähetetään pian linkki salasanan vaihtoon. Jos et saa viestiä, tarkista roskapostikansio.
+ updated: Salasanan vaihto onnistui. Olet nyt kirjautunut sisään.
+ updated_not_active: Salasanan vaihto onnistui.
registrations:
- destroyed: Näkemiin! Tilisi on onnistuneesti peruttu. Toivottavasti näemme joskus uudestaan.
- signed_up: Tervetuloa! Rekisteröitymisesi onnistu.
- signed_up_but_inactive: Olet onnistuneesti rekisteröitynyt, mutta emme voi kirjata sinua sisään koska tiliäsi ei ole viellä aktivoitu.
- signed_up_but_locked: Olet onnistuneesti rekisteröitynyt, mutta emme voi kirjata sinua sisään koska tilisi on lukittu.
- signed_up_but_unconfirmed: Varmistuslinkki on lähetty sähköpostiisi. Seuraa sitä jotta tilisi voidaan aktivoida.
- update_needs_confirmation: Tilisi on onnistuneesti päivitetty, mutta meidän tarvitsee vahvistaa sinun uusi sähköpostisi. Tarkista sähköpostisi ja seuraa viestissä tullutta linkkiä varmistaaksesi uuden osoitteen..
- updated: Tilisi on onnistuneesti päivitetty.
+ destroyed: Tilisi on poistettu. Näkemiin ja tervetuloa uudelleen!
+ signed_up: Tervetuloa! Rekisteröityminen onnistui.
+ signed_up_but_inactive: Rekisteröityminen onnistui. Emme kuitenkaan voi kirjata sinua sisään, sillä tiliäsi ei ole vielä aktivoitu.
+ signed_up_but_locked: Rekisteröityminen onnistui. Emme kuitenkaan voi kirjata sinua sisään, sillä tilisi on lukittu.
+ signed_up_but_unconfirmed: Sähköpostiosoitteeseesi on lähetetty vahvistuslinkki. Aktivoi tili seuraamalla linkkiä. Jos et saanut viestiä, tarkista roskapostikansio.
+ update_needs_confirmation: Tilin päivitys onnistui, mutta uusi sähköpostiosoite on vahvistettava. Tarkista sähköpostisi ja vahvista uusi sähköpostiosoite seuraamalla vahvistuslinkkiä. Jos et saanut viestiä, tarkista roskapostikansio.
+ updated: Tilin päivitys onnistui.
sessions:
- already_signed_out: Ulos kirjautuminen onnistui.
+ already_signed_out: Uloskirjautuminen onnistui.
signed_in: Sisäänkirjautuminen onnistui.
- signed_out: Ulos kirjautuminen onnistui.
+ signed_out: Uloskirjautuminen onnistui.
unlocks:
- send_instructions: Saat sähköpostiisi pian ohjeet, jolla voit avata tilisi uudestaan.
- send_paranoid_instructions: Jos tilisi on olemassa, saat sähköpostiisi pian ohjeet tilisi avaamiseen.
- unlocked: Tilisi on avattu onnistuneesti. Kirjaudu normaalisti sisään.
+ send_instructions: Saat pian sähköpostitse ohjeet tilin lukituksen poistoon. Jos et saanut viestiä, tarkista roskapostikansio.
+ send_paranoid_instructions: Jos tili on olemassa, saat pian sähköpostitse ohjeet tilin lukituksen poistoon. Jos et saanut viestiä, tarkista roskapostikansio.
+ unlocked: Tilin lukituksen poisto onnistui. Jatka kirjautumalla sisään.
errors:
messages:
- already_confirmed: on jo varmistettu. Yritä kirjautua sisään
- confirmation_period_expired: pitää varmistaa %{period} sisällä, ole hyvä ja pyydä uusi
- expired: on erääntynyt, ole hyvä ja pyydä uusi
+ already_confirmed: on jo vahvistettu. Yritä kirjautua sisään
+ confirmation_period_expired: on vahvistettava %{period} sisällä. Pyydä uusi
+ expired: on vanhentunut. Pyydä uusi
not_found: ei löydy
not_locked: ei ollut lukittu
not_saved:
- one: '1 virhe esti %{resource} tallennuksen:'
- other: "%{count} virhettä esti %{resource} tallennuksen:"
+ one: '1 virhe esti kohteen %{resource} tallennuksen:'
+ other: "%{count} virhettä esti kohteen %{resource} tallennuksen:"
diff --git a/config/locales/devise.sk.yml b/config/locales/devise.sk.yml
index 2ce328d22..e9c5dd455 100644
--- a/config/locales/devise.sk.yml
+++ b/config/locales/devise.sk.yml
@@ -13,13 +13,13 @@ sk:
locked: Váš účet je zamknutý.
not_found_in_database: Nesprávny %{authentication_keys} alebo heslo.
timeout: Vaša aktívna sezóna vypršala. Pre pokračovanie sa prosím znovu prihláste.
- unauthenticated: Pred pokračovaním sa musíte zaregistrovať alebo prihlásiť.
- unconfirmed: Pred pokračovaním musíte potvrdiť svoj email.
+ unauthenticated: K pokračovaniu sa musíš zaregistrovať alebo prihlásiť.
+ unconfirmed: Pred pokračovaním musíš potvrdiť svoj email.
mailer:
confirmation_instructions:
- action: Potvrite emailovú adresu
- explanation: S touto email adresou ste si vytvoril/a účet na %{host}. Si iba jeden klik od jeho aktivácie. Pokiaľ ste to ale nebol/a vy, prosím ignoruj tento email.
- extra_html: Prosím pozri sa aj na pravidla tohto servera, a naše užívaťeľské podiemky.
+ action: Potvŕď emailovú adresu
+ explanation: S touto emailovou adresou si si vytvoril/a účet na %{host}. Si iba jeden klik od jeho aktivácie. Pokiaľ si to ale nebol/a ty, prosím ignoruj tento email.
+ extra_html: Prosím pozri sa aj na pravidlá tohto servera, a naše užívaťeľské podiemky.
subject: 'Mastodon: Potvrdzovacie inštrukcie pre %{instance}'
title: Potvrď emailovú adresu
email_changed:
diff --git a/config/locales/doorkeeper.fi.yml b/config/locales/doorkeeper.fi.yml
index 8c1baf909..a3b878b65 100644
--- a/config/locales/doorkeeper.fi.yml
+++ b/config/locales/doorkeeper.fi.yml
@@ -3,17 +3,19 @@ fi:
activerecord:
attributes:
doorkeeper/application:
- name: Nimi
- redirect_uri: Uudelleenohjaus URI
+ name: Sovelluksen nimi
+ redirect_uri: Uudelleenohjauksen URI
+ scopes: Oikeudet
+ website: Sovelluksen verkkosivu
errors:
models:
doorkeeper/application:
attributes:
redirect_uri:
fragment_present: ei voi sisältää osia.
- invalid_uri: pitää olla validi URI.
- relative_uri: pitää olla täydellinen URI.
- secured_uri: pitää olla HTTPS/SSL URI.
+ invalid_uri: on oltava kelvollinen URI.
+ relative_uri: on oltava täydellinen URI.
+ secured_uri: on oltava HTTPS/SSL-URI.
doorkeeper:
applications:
buttons:
@@ -25,89 +27,93 @@ fi:
confirmations:
destroy: Oletko varma?
edit:
- title: Muokkaa applikaatiota
+ title: Muokkaa sovellusta
form:
- error: Whoops! Tarkista lomakkeesi mahdollisten virheiden varalta
+ error: Hups! Tarkista, että lomakkeessa ei ole virheitä
help:
native_redirect_uri: Käytä %{native_redirect_uri} paikallisiin testeihin
- redirect_uri: Käytä yhtä riviä per URI
- scopes: Erota scopet välilyönnein. Jätä tyhjäksi käyteksi oletus scopeja.
+ redirect_uri: Lisää jokainen URI omalle rivilleen
+ scopes: Erota oikeudet välilyönnein. Jos kenttä jätetään tyhjäksi, käytetään oletusoikeuksia.
index:
- callback_url: Callback URL
+ application: Sovellus
+ callback_url: Takaisinkutsu-URL
+ delete: Poista
name: Nimi
- new: Uusi applikaatio
- title: Sinun applikaatiosi
+ new: Uusi sovellus
+ scopes: Oikeudet
+ show: Näytä
+ title: Omat sovellukset
new:
- title: Uusi applikaatio
+ title: Uusi sovellus
show:
actions: Toiminnot
- application_id: Applikaation Id
- callback_urls: Callback urls
- scopes: Scopet
- secret: Salainen avain
- title: 'Applikaatio: %{name}'
+ application_id: Asiakasohjelman tunnus
+ callback_urls: Takaisinkutsu-URL:t
+ scopes: Oikeudet
+ secret: Asiakasohjelman salainen avain
+ title: 'Sovellus: %{name}'
authorizations:
buttons:
authorize: Valtuuta
deny: Evää
error:
- title: Virhe on tapahtunut
+ title: Tapahtui virhe
new:
able_to: Se voi
- prompt: Applikaatio %{client_name} pyytää lupaa tilillesi
+ prompt: Sovellus %{client_name} pyytää lupaa käyttää tiliäsi
title: Valtuutus vaaditaan
show:
- title: Kopioi tämä valtuutuskoodi ja liitä se applikaatioon.
+ title: Kopioi tämä valtuutuskoodi ja liitä se sovellukseen.
authorized_applications:
buttons:
- revoke: Evää
+ revoke: Peru
confirmations:
revoke: Oletko varma?
index:
- application: Applikaatio
+ application: Sovellus
created_at: Valtuutettu
date_format: "%Y-%m-%d %H:%M:%S"
- scopes: Scopet
- title: Valtuuttamasi applikaatiot
+ scopes: Oikeudet
+ title: Valtuutetut sovellukset
errors:
messages:
- access_denied: Resurssin omistaja tai valtuutus palvelin hylkäsi pyynnönr.
- credential_flow_not_configured: Resurssin omistajan salasana epäonnistui koska Doorkeeper.configure.resource_owner_from_credentials ei ole konfiguroitu.
- invalid_client: Asiakkaan valtuutus epäonnistui koska tuntematon asiakas, asiakas ei sisältänyt valtuutusta, tai tukematon valtuutus tapa.
- invalid_grant: Antamasi valtuutus lupa on joko väärä, erääntynyt, peruttu, ei vastaa uudelleenohjaus URI jota käytetään valtuutus pyynnössä, tai se myönnettin toiselle asiakkaalle.
- invalid_redirect_uri: Uudelleenohjaus uri ei ole oikein.
- invalid_request: Pyynnöstä puutti parametri, sisältää tukemattoman parametri arvonn, tai on korruptoitunut.
- invalid_resource_owner: Annetut resurssin omistajan tunnnukset ovat väärät, tai resurssin omistajaa ei löydy
- invalid_scope: Pyydetty scope on väärä, tuntemat, tai korruptoitunut.
+ access_denied: Resurssin omistaja tai valtuutuspalvelin hylkäsi pyynnön.
+ credential_flow_not_configured: Resurssin omistajan salasana epäonnistui, koska asetusta Doorkeeper.configure.resource_owner_from_credentials ei ole konfiguroitu.
+ invalid_client: Asiakasohjelman valtuutus epäonnistui, koska asiakas on tuntematon, asiakkaan valtuutus ei ollut mukana tai valtuutustapaa ei tueta.
+ invalid_grant: Valtuutuslupa on virheellinen, umpeutunut, peruttu, valtuutuspyynnössä käytettyä uudelleenohjaus-URI:tä vastaamaton tai myönnetty toiselle asiakkaalle.
+ invalid_redirect_uri: Uudelleenohjaus-URI on virheellinen.
+ invalid_request: Pyynnöstä puuttuu vaadittu parametri, se sisältää tukemattoman parametriarvon tai on muulla tavoin väärin muotoiltu.
+ invalid_resource_owner: Annetut resurssin omistajan tunnnukset ovat virheelliset, tai resurssin omistajaa ei löydy
+ invalid_scope: Pyydetyt oikeudet ovat virheellisiä, tuntemattomia tai väärin muotoiltuja.
invalid_token:
- expired: Access token vanhentunut
- revoked: Access token evätty
- unknown: Access token väärä
- resource_owner_authenticator_not_configured: Resurssin omistajan etsiminen epäonnistui koska Doorkeeper.configure.resource_owner_authenticator ei ole konfiguroitu.
- server_error: Valtuutus palvelin kohtasi odottamattoman virheen joka esti sitä täyttämästä pyyntöä.
- temporarily_unavailable: Valtuutus palvelin ei voi tällä hetkellä käsitellä pyyntöäsi joko väliaikaisen ruuhkan tai huollon takia.
- unauthorized_client: Asiakas ei ole valtuutettu tekemään tätä pyyntöä käyttäen tätä metodia.
- unsupported_grant_type: Valtuutus grant type ei ole tuettu valtuutus palvelimella.
- unsupported_response_type: Valtuutus palvelin ei tue tätä vastaus tyyppiä.
+ expired: Käyttöoikeustunnus on vanhentunut
+ revoked: Käyttöoikeustunnus on peruttu
+ unknown: Käyttöoikeustunnus on virheellinen
+ resource_owner_authenticator_not_configured: Resurssin omistajaa ei löytynyt, koska asetusta Doorkeeper.configure.resource_owner_authenticator ei ole konfiguroitu.
+ server_error: Valtuutuspalvelin kohtasi odottamattoman virheen, joka esti pyynnön täyttämisen.
+ temporarily_unavailable: Valtuutuspalvelin ei voi tällä hetkellä käsitellä pyyntöä joko väliaikaisen ruuhkan tai huollon takia.
+ unauthorized_client: Asiakkaalla ei ole valtuuksia tehdä tätä pyyntöä tällä metodilla.
+ unsupported_grant_type: Valtuutuspalvelin ei tue tätä valtuutusluvan tyyppiä.
+ unsupported_response_type: Valtuutuspalvelin ei tue tätä vastauksen tyyppiä.
flash:
applications:
create:
- notice: Applikaatio luotu.
+ notice: Sovellus luotu.
destroy:
- notice: Applikaatio poistettu.
+ notice: Sovellus poistettu.
update:
- notice: Applikaatio päivitetty.
+ notice: Sovellus päivitetty.
authorized_applications:
destroy:
- notice: Applikaatio tuhottu.
+ notice: Sovellus peruttu.
layouts:
admin:
nav:
- applications: Applikaatiot
- oauth2_provider: OAuth2 Provider
+ applications: Sovellukset
+ oauth2_provider: OAuth2-palveluntarjoaja
application:
- title: OAuth valtuutus tarvitaan
+ title: OAuth-valtuutus tarvitaan
scopes:
- follow: seuraa, estä, peru esto ja lopeta tilien seuraaminen
- read: lukea tilin dataa
+ follow: seurata, estää, perua eston ja lopettaa tilien seuraaminen
+ read: lukea tilin tietoja
write: julkaista puolestasi
diff --git a/config/locales/doorkeeper.sk.yml b/config/locales/doorkeeper.sk.yml
index 7a285eb4f..bda26429e 100644
--- a/config/locales/doorkeeper.sk.yml
+++ b/config/locales/doorkeeper.sk.yml
@@ -63,7 +63,7 @@ sk:
prompt: Aplikácia %{client_name} žiada prístup k vašemu účtu
title: Je potrebná autorizácia
show:
- title: Skopírujte tento autorizačný kód a vložte ho do aplikácie.
+ title: Skopíruj tento autorizačný kód a vlož ho do aplikácie.
authorized_applications:
buttons:
revoke: Zrušiť oprávnenie
diff --git a/config/locales/eo.yml b/config/locales/eo.yml
index a896592b0..27c62f899 100644
--- a/config/locales/eo.yml
+++ b/config/locales/eo.yml
@@ -24,12 +24,12 @@ eo:
within_reach_body: Pluraj aplikaĵoj por iOS, Android, kaj aliaj platformoj danke al API-medio bonveniga por programistoj permesas resti en kontakto kun viaj amikoj ĉie.
within_reach_title: Ĉiam kontaktebla
generic_description: "%{domain} estas unu servilo en la reto"
- hosted_on: Mastodon gastigita en %{domain}
+ hosted_on: "%{domain} estas nodo de Mastodon"
learn_more: Lerni pli
other_instances: Listo de nodoj
source_code: Fontkodo
status_count_after: mesaĝoj
- status_count_before: Kiu publikigis
+ status_count_before: Kie skribiĝis
user_count_after: uzantoj
user_count_before: Hejmo de
what_is_mastodon: Kio estas Mastodon?
@@ -358,7 +358,7 @@ eo:
warning: Estu tre atenta kun ĉi tiu datumo. Neniam diskonigu ĝin al iu ajn!
your_token: Via alira ĵetono
auth:
- agreement_html: Per registriĝo, vi konsentas kun la reguloj de la nodo kaj niaj uzkondiĉoj.
+ agreement_html: Per registriĝo, vi konsentas kun la reguloj de nia nodo kaj niaj uzkondiĉoj.
change_password: Pasvorto
confirm_email: Konfirmi retadreson
delete_account: Forigi konton
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 8e7a766a8..a5a20aa3c 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -546,7 +546,7 @@ es:
quadrillion: Q
thousand: K
trillion: T
- unit: ''
+ unit: " "
pagination:
newer: Más nuevo
next: Próximo
@@ -634,6 +634,15 @@ es:
two_factor_authentication: Autenticación de dos factores
your_apps: Tus aplicaciones
statuses:
+ attached:
+ description: 'Adjunto: %{attached}'
+ image:
+ one: "%{count} imagen"
+ other: "%{count} imágenes"
+ video:
+ one: "%{count} vídeo"
+ other: "%{count} vídeos"
+ content_warning: 'Alerta de contenido: %{warning}'
open_in_web: Abrir en web
over_character_limit: Límite de caracteres de %{max} superado
pin_errors:
@@ -682,7 +691,7 @@ es:
backup_ready:
explanation: Has solicitado una copia completa de tu cuenta de Mastodon. ¡Ya está preparada para descargar!
subject: Tu archivo está preparado para descargar
- title: Recogida del archivo
+ title: Descargar archivo
welcome:
edit_profile_action: Configurar el perfil
edit_profile_step: Puedes personalizar tu perfil subiendo un avatar, cabecera, cambiando tu nombre para mostrar y más. Si te gustaría revisar seguidores antes de autorizarlos a que te sigan, puedes bloquear tu cuenta.
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 939ebd10a..62f6560bf 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -1,31 +1,35 @@
---
fi:
about:
- about_mastodon_html: Mastodon on vapaa, avoimeen lähdekoodiin perustuva sosiaalinen verkosto. Hajautettu vaihtoehto kaupallisille alustoille, se välttää eiskit yhden yrityksen monopolisoinnin sinun viestinnässäsi. Valitse palvelin mihin luotat — minkä tahansa valitset, voit vuorovaikuttaa muiden kanssa. Kuka tahansa voi luoda Mastodon palvelimen ja ottaa osaa sosiaaliseen verkkoon saumattomasti.
+ about_hashtag_html: Nämä ovat hashtagilla #%{hashtag} merkittyjä julkisia tuuttauksia. Voit vastata niihin, jos sinulla on tili jossain päin fediversumia.
+ about_mastodon_html: Mastodon on sosiaalinen verkosto. Se on toteutettu avoimilla verkkoprotokollilla ja vapailla, avoimen lähdekoodin ohjelmistoilla, ja se toimii hajautetusti samaan tapaan kuin sähköposti.
about_this: Tietoja tästä palvelimesta
- closed_registrations: Rekisteröityminen tässä instanssissa on juuri nyt suljettu. Mutta! Voit yhdistää täysin samaan, yhteiseen verkostoon rekisteröitymällä jossain toisessa instanssissa.
+ closed_registrations: Tähän instanssiin ei voi tällä hetkellä rekisteröityä. Voit kuitenkin luoda tilin johonkin toiseen instanssiin ja käyttää samaa verkostoa sitä kautta.
contact: Ota yhteyttä
contact_missing: Ei asetettu
contact_unavailable: Ei saatavilla
description_headline: Mikä on %{domain}?
- domain_count_after: muuhun palvelimeen
+ domain_count_after: muuhun instanssiin
domain_count_before: Yhdistyneenä
extended_description_html: |
Hyvä paikka säännöille
-
Pidennettyä kuvausta ei ole vielä asetettu.
+
Pidempää kuvausta ei ole vielä laadittu.
features:
- humane_approach_body: Muiden verkostojen virheistä oppien, Mastodon pyrkii tekemään eettisiä valintoja suunnittelussa taistellakseen sosiaalisen median väärinkäyttöä vastaan.
- humane_approach_title: Humaanimpi lähestymistapa
- not_a_product_body: Mastodon ei ole kaupallinen verkosto. Ei mainoksia, ei tiedonlouhintaa, ei suljettuja sisäpiirejä. Mastodonissa ei ole keskitettyä auktoriteettiä.
+ humane_approach_body: Mastodonissa otetaan oppia muiden verkostojen virheistä, ja sen suunnittelussa pyritään toimimaan eettisesti ja ehkäisemään sosiaalisen median väärinkäyttöä.
+ humane_approach_title: Ihmisläheisempi ote
+ not_a_product_body: Mastodon ei ole kaupallinen verkosto. Ei mainoksia, ei tiedonlouhintaa, ei suljettuja protokollia. Mastodonissa ei ole keskusjohtoa.
not_a_product_title: Olet henkilö, et tuote
- real_conversation_title: Rakennettu oikealle keskustelulle
- within_reach_body: Kehittäjäystävällisen rajapintaekosysteemin ansiosta useita appeja Androidille, iOS:lle ja muille alustoille, jotka mahdollistavat yhteydenpidon ystäviesi kanssa missä vain.
+ real_conversation_body: 'Voit ilmaista itseäsi niin kuin itse haluat: tilaa on 500 merkkiä, ja sisältövaroituksia voi tehdä monin tavoin.'
+ real_conversation_title: Tehty oikeaa keskustelua varten
+ within_reach_body: Rajapintoja on tarjolla moniin eri kehitysympäristöihin, minkä ansiosta iOS:lle, Androidille ja muille alustoille on saatavana useita eri sovelluksia. Näin voit pitää yhteyttä ystäviisi missä vain.
within_reach_title: Aina lähellä
+ generic_description: "%{domain} on yksi verkostoon kuuluvista palvelimista"
+ hosted_on: Mastodon palvelimella %{domain}
learn_more: Lisätietoja
other_instances: Muut palvelimet
source_code: Lähdekoodi
status_count_after: statusta
- status_count_before: Ovat luoneet
+ status_count_before: He ovat luoneet
user_count_after: käyttäjälle
user_count_before: Koti
what_is_mastodon: Mikä on Mastodon?
@@ -33,161 +37,681 @@ fi:
follow: Seuraa
followers: Seuraajat
following: Seuratut
+ media: Media
+ moved_html: "%{name} on muuttanut osoitteeseen %{new_profile_link}:"
nothing_here: Täällä ei ole mitään!
- people_followed_by: Henkilöitä joita %{name} seuraa
- people_who_follow: Henkilöt jotka seuraa %{name}
- posts: Postaukset
+ people_followed_by: Henkilöt, joita %{name} seuraa
+ people_who_follow: Käyttäjän %{name} seuraajat
+ posts: Tuuttaukset
+ posts_with_replies: Tuuttaukset ja vastaukset
remote_follow: Etäseuranta
reserved_username: Käyttäjänimi on varattu
roles:
admin: Ylläpitäjä
+ moderator: Moderaattori
unfollow: Lopeta seuraaminen
admin:
account_moderation_notes:
account: Moderaattori
create: Luo
created_at: Päiväys
- created_msg: Moderointimerkintä luotu onnistuneesti!
+ created_msg: Moderointimerkinnän luonti onnistui!
delete: Poista
- destroyed_msg: Moderointimerkintä tuhottu onnistuneesti!
+ destroyed_msg: Moderointimerkinnän poisto onnistui!
accounts:
are_you_sure: Oletko varma?
- confirm: Hyväksy
- confirmed: Hyväksytty
+ by_domain: Verkko-osoite
+ confirm: Vahvista
+ confirmed: Vahvistettu
+ demote: Alenna
disable: Poista käytöstä
disable_two_factor_authentication: Poista 2FA käytöstä
disabled: Poistettu käytöstä
+ display_name: Näyttönimi
+ domain: Verkko-osoite
edit: Muokkaa
email: Sähköposti
+ enable: Ota käyttöön
+ enabled: Käytössä
+ feed_url: Syötteen URL
followers: Seuraajat
- followers_url: Seuraajat URL
+ followers_url: Seuraajien URL
+ follows: Seuraa
+ inbox_url: Saapuvan postilaatikon URL
+ ip: IP
+ location:
+ all: Kaikki
+ local: Paikalliset
+ remote: Etätilit
+ title: Sijainti
+ login_status: Sisäänkirjautumisen tila
+ media_attachments: Medialiitteet
+ memorialize: Muuta muistosivuksi
+ moderation:
+ all: Kaikki
+ silenced: Hiljennetty
+ suspended: Jäähyllä
+ title: Moderointi
+ moderation_notes: Moderointimerkinnät
+ most_recent_activity: Viimeisin toiminta
+ most_recent_ip: Viimeisin IP
+ not_subscribed: Ei tilaaja
+ order:
+ alphabetic: Aakkosjärjestys
+ most_recent: Uusin
+ title: Järjestys
+ outbox_url: Lähtevän postilaatikon URL
+ perform_full_suspension: Siirrä kokonaan jäähylle
+ profile_url: Profiilin URL
+ promote: Ylennä
+ protocol: Protokolla
+ public: Julkinen
+ push_subscription_expires: PuSH-tilaus vanhenee
+ redownload: Päivitä profiilikuva
+ reset: Palauta
+ reset_password: Palauta salasana
+ resubscribe: Tilaa uudelleen
+ role: Oikeudet
+ roles:
+ admin: Ylläpitäjä
+ moderator: Moderaattori
+ staff: Henkilöstö
+ user: Käyttäjä
+ salmon_url: Salmon-URL
+ search: Haku
+ shared_inbox_url: Jaetun saapuvan postilaatikon URL
+ show:
+ created_reports: Tilin luomat raportit
+ report: raportti
+ targeted_reports: Tästä tilistä tehdyt raportit
+ silence: Hiljennä
+ statuses: Tilat
+ subscribe: Tilaa
+ title: Tilit
+ undo_silenced: Peru hiljennys
+ undo_suspension: Peru jäähy
+ unsubscribe: Lopeta tilaus
+ username: Käyttäjänimi
+ web: Web
+ action_logs:
+ actions:
+ confirm_user: "%{name} vahvisti käyttäjän %{target} sähköpostiosoitteen"
+ create_custom_emoji: "%{name} lähetti uuden emojin %{target}"
+ create_domain_block: "%{name} esti verkkotunnuksen %{target}"
+ create_email_domain_block: "%{name} lisäsi sähköpostiverkkotunnuksen %{target} estolistalle"
+ demote_user: "%{name} alensi käyttäjän %{target}"
+ destroy_domain_block: "%{name} poisti verkkotunnuksen %{target} eston"
+ destroy_email_domain_block: "%{name} lisäsi sähköpostiverkkotunnuksen %{target} sallittujen listalle"
+ destroy_status: "%{name} poisti käyttäjän %{target} tilan"
+ disable_2fa_user: "%{name} poisti käyttäjältä %{target} kaksivaiheisen todentamisen vaatimuksen"
+ disable_custom_emoji: "%{name} poisti emojin %{target} käytöstä"
+ disable_user: "%{name} poisti sisäänkirjautumisen käytöstä käyttäjältä %{target}"
+ enable_custom_emoji: "%{name} salli emojin %{target} käyttöön"
+ enable_user: "%{name} salli sisäänkirjautumisen käyttäjälle %{target}"
+ memorialize_account: "%{name} muutti käyttäjän %{target} tilin muistosivuksi"
+ promote_user: "%{name} ylensi käyttäjän %{target}"
+ reset_password_user: "%{name} palautti käyttäjän %{target} salasanan"
+ resolve_report: "%{name} hylkäsi raportin %{target}"
+ silence_account: "%{name} hiljensi käyttäjän %{target}"
+ suspend_account: "%{name} siirsi käyttäjän %{target} jäähylle"
+ unsilence_account: "%{name} poisti käyttäjän %{target} hiljennyksen"
+ unsuspend_account: "%{name} perui käyttäjän %{target} jäähyn"
+ update_custom_emoji: "%{name} päivitti emojin %{target}"
+ update_status: "%{name} päivitti käyttäjän %{target} tilan"
+ title: Auditointiloki
+ custom_emojis:
+ by_domain: Verkkotunnus
+ copied_msg: Emojin paikallisen kopion luonti onnistui
+ copy: Kopioi
+ copy_failed_msg: Emojista ei voitu tehdä paikallista kopiota
+ created_msg: Emojin luonti onnistui!
+ delete: Poista
+ destroyed_msg: Emojon poisto onnistui!
+ disable: Poista käytöstä
+ disabled_msg: Emojin käytöstäpoisto onnistui
+ emoji: Emoji
+ enable: Ota käyttöön
+ enabled_msg: Emojin käyttöönotto onnistui
+ image_hint: PNG enintään 50 kt
+ listed: Listassa
+ new:
+ title: Lisää uusi mukautettu emoji
+ overwrite: Kirjoita yli
+ shortcode: Lyhennekoodi
+ shortcode_hint: Vähintään kaksi merkkiä, vain kirjaimia, numeroita ja alaviivoja
+ title: Mukautetut emojit
+ unlisted: Ei listassa
+ update_failed_msg: Emojin päivitys epäonnistui
+ updated_msg: Emojin päivitys onnistui!
+ upload: Lähetä
+ domain_blocks:
+ add_new: Lisää uusi
+ created_msg: Verkkotunnuksen estoa käsitellään
+ destroyed_msg: Verkkotunnuksen esto on peruttu
+ domain: Verkkotunnus
+ new:
+ create: Luo esto
+ hint: Verkkotunnuksen esto ei estä tilien luomista ja lisäämistä tietokantaan, mutta se soveltaa näihin tileihin automaattisesti määrättyjä moderointitoimia tilin luomisen jälkeen.
+ severity:
+ desc_html: "Hiljennys estää tilin julkaisuja näkymästä muille kuin tilin seuraajille. Jäähy poistaa tilin kaiken sisällön, median ja profiilitiedot. Jos haluat vain hylätä mediatiedostot, valitse Ei mitään."
+ noop: Ei mitään
+ silence: Hiljennys
+ suspend: Jäähy
+ title: Uusi verkkotunnuksen esto
+ reject_media: Hylkää mediatiedostot
+ reject_media_hint: Poistaa paikallisesti tallennetut mediatiedostot eikä lataa niitä enää jatkossa. Ei merkitystä jäähyn kohdalla
+ severities:
+ noop: Ei mitään
+ silence: Hiljennys
+ suspend: Jäähy
+ severity: Vakavuus
+ show:
+ affected_accounts:
+ one: Vaikuttaa yhteen tiliin tietokannassa
+ other: Vaikuttaa %{count} tiliin tietokannassa
+ retroactive:
+ silence: Peru kaikkien tässä verkkotunnuksessa jo olemassa olevien tilien hiljennys
+ suspend: Peru kaikkien tässä verkkotunnuksessa jo olemassa olevien tilien jäähy
+ title: Peru verkkotunnuksen %{domain} esto
+ undo: Peru
+ title: Verkkotunnusten estot
+ undo: Peru
+ email_domain_blocks:
+ add_new: Lisää uusi
+ created_msg: Sähköpostiverkkotunnuksen lisäys estolistalle onnistui
+ delete: Poista
+ destroyed_msg: Sähköpostiverkkotunnuksen poisto estolistalta onnistui
+ domain: Verkkotunnus
+ new:
+ create: Lisää verkkotunnus
+ title: Uusi sähköpostiestolistan merkintä
+ title: Sähköpostiestolista
+ instances:
+ account_count: Tiedossa olevat tilit
+ domain_name: Verkkotunnus
+ reset: Palauta
+ search: Hae
+ title: Tiedossa olevat instanssit
+ invites:
+ filter:
+ all: Kaikki
+ available: Saatavilla
+ expired: Vanhentunut
+ title: Suodata
+ title: Kutsut
+ reports:
+ action_taken_by: Toimenpiteen tekijä
+ are_you_sure: Oletko varma?
+ comment:
+ label: Kommentti
+ none: Ei mitään
+ delete: Poista
+ id: Tunniste
+ mark_as_resolved: Merkitse ratkaistuksi
+ nsfw:
+ 'false': Peru medialiitteiden piilotus
+ 'true': Piilota medialiitteet
+ report: Raportti nro %{id}
+ report_contents: Sisältö
+ reported_account: Raportoitu tili
+ reported_by: Raportoija
+ resolved: Ratkaistut
+ silence_account: Hiljennä tili
+ status: Tila
+ suspend_account: Siirrä tili jäähylle
+ target: Kohde
+ title: Raportit
+ unresolved: Ratkaisemattomat
+ view: Näytä
+ settings:
+ activity_api_enabled:
+ desc_html: Paikallisesti julkaistujen tilojen, aktiivisten käyttäjien ja uusien rekisteröintien määrät viikoittain
+ title: Julkaise koostetilastoja käyttäjien aktiivisuudesta
+ bootstrap_timeline_accounts:
+ desc_html: Erota käyttäjänimet pilkulla. Vain paikalliset ja lukitsemattomat tilit toimivat. Jos kenttä jätetään tyhjäksi, oletusarvona ovat kaikki paikalliset ylläpitäjät.
+ title: Uudet käyttäjät seuraavat oletuksena seuraavia tilejä
+ contact_information:
+ email: Työsähköposti
+ username: Yhteyshenkilön käyttäjänimi
+ hero:
+ desc_html: Näytetään etusivulla. Suosituskoko vähintään 600x100 pikseliä. Jos kuvaa ei aseteta, käytetään instanssin pikkukuvaa
+ title: Sankarin kuva
+ peers_api_enabled:
+ desc_html: Verkkotunnukset, jotka tämä instanssi on kohdannut fediversumissa
+ title: Julkaise löydettyjen instanssien luettelo
+ registrations:
+ closed_message:
+ desc_html: Näytetään etusivulla, kun rekisteröinti on suljettu. HTML-tagit käytössä
+ title: Viesti, kun rekisteröinti on suljettu
+ deletion:
+ desc_html: Salli jokaisen poistaa oma tilinsä
+ title: Avoin tilin poisto
+ min_invite_role:
+ disabled: Ei kukaan
+ title: Salli kutsut käyttäjältä
+ open:
+ desc_html: Salli kenen tahansa luoda tili
+ title: Avoin rekisteröinti
+ show_known_fediverse_at_about_page:
+ desc_html: Kun tämä on valittu, esikatselussa näytetään tuuttaukset kaikkialta tunnetusta fediversumista. Muutoin näytetään vain paikalliset tuuttaukset.
+ title: Näytä aikajanan esikatselussa koko tunnettu fediversumi
+ show_staff_badge:
+ desc_html: Näytä käyttäjäsivulla henkilöstömerkki
+ title: Näytä henkilöstömerkki
+ site_description:
+ desc_html: Esittelykappale etusivulla ja metatunnisteissa. HTML-tagit käytössä, tärkeimmät ovat <a> ja <em>.
+ title: Instanssin kuvaus
+ site_description_extended:
+ desc_html: Hyvä paikka käytösohjeille, säännöille, ohjeistuksille ja muille instanssin muista erottaville asioille. HTML-tagit käytössä
+ title: Omavalintaiset laajat tiedot
+ site_terms:
+ desc_html: Tähän voi kirjoittaa instanssin tietosuojakäytännöstä, käyttöehdoista ja sen sellaisista asioista. HTML-tagit käytössä
+ title: Omavalintaiset käyttöehdot
+ site_title: Instanssin nimi
+ thumbnail:
+ desc_html: Käytetään esikatseluissa OpenGraphin ja API:n kautta. Suosituskoko 1200x630 pikseliä
+ title: Instanssin pikkukuva
+ timeline_preview:
+ desc_html: Näytä julkinen aikajana aloitussivulla
+ title: Aikajanan esikatselu
+ title: Sivuston asetukset
+ statuses:
+ back_to_account: Takaisin tilin sivulle
+ batch:
+ delete: Poista
+ nsfw_off: NSFW POIS
+ nsfw_on: NSFW PÄÄLLÄ
+ execute: Suorita
+ failed_to_execute: Suoritus epäonnistui
+ media:
+ hide: Piilota media
+ show: Näytä media
+ title: Media
+ no_media: Ei mediaa
+ title: Tilin tilat
+ with_media: Sisältää mediaa
+ subscriptions:
+ callback_url: Paluu-URL
+ confirmed: Vahvistettu
+ expires_in: Vanhenee
+ last_delivery: Viimeisin toimitus
+ title: WebSub
+ topic: Aihe
+ title: Ylläpito
+ admin_mailer:
+ new_report:
+ body: "%{reporter} on raportoinut kohteen %{target}"
+ subject: Uusi raportti instanssista %{instance} (nro %{id})
application_mailer:
- settings: 'Muokkaa sähköpostiasetuksia: %{link}'
- view: 'Katso:'
+ notification_preferences: Muuta sähköpostiasetuksia
+ salutation: "%{name},"
+ settings: 'Muuta sähköpostiasetuksia: %{link}'
+ view: 'Näytä:'
+ view_profile: Näytä profiili
+ view_status: Näytä tila
applications:
- invalid_url: Annettu URL on väärä
+ created: Sovelluksen luonti onnistui
+ destroyed: Sovelluksen poisto onnistui
+ invalid_url: Annettu URL on virheellinen
+ regenerate_token: Luo pääsytunnus uudelleen
+ token_regenerated: Pääsytunnuksen uudelleenluonti onnistui
+ warning: Säilytä tietoa hyvin. Älä milloinkaan jaa sitä muille!
+ your_token: Pääsytunnus
auth:
- didnt_get_confirmation: Etkö saanut varmennusohjeita?
+ agreement_html: Rekisteröityessäsi sitoudut noudattamaan instanssin sääntöjä ja käyttöehtoja.
+ change_password: Salasana
+ confirm_email: Vahvista sähköpostiosoite
+ delete_account: Poista tili
+ delete_account_html: Jos haluat poistaa tilisi, paina tästä. Poisto on vahvistettava.
+ didnt_get_confirmation: Etkö saanut vahvistusohjeita?
forgot_password: Unohditko salasanasi?
+ invalid_reset_password_token: Salasananpalautustunnus on virheellinen tai vanhentunut. Pyydä uusi.
login: Kirjaudu sisään
logout: Kirjaudu ulos
+ migrate_account: Muuta toiseen tiliin
+ migrate_account_html: Jos haluat ohjata tämän tilin toiseen tiliin, voit asettaa toisen tilin tästä.
+ or: tai
+ or_log_in_with: Tai käytä kirjautumiseen
+ providers:
+ cas: CAS
+ saml: SAML
register: Rekisteröidy
- resend_confirmation: Lähetä varmennusohjeet uudestaan
+ register_elsewhere: Rekisteröidy toiselle palvelimelle
+ resend_confirmation: Lähetä vahvistusohjeet uudestaan
reset_password: Palauta salasana
security: Tunnukset
set_new_password: Aseta uusi salasana
authorize_follow:
- error: Valitettavasti tapahtui virhe etätilin haussa.
+ error: Valitettavasti etätilin haussa tapahtui virhe
follow: Seuraa
- title: Seuraa %{acct}
+ follow_request: 'Olet lähettänyt seuraamispyynnön käyttäjälle:'
+ following: 'Onnistui! Seuraat käyttäjää:'
+ post_follow:
+ close: Tai voit sulkea tämän ikkunan.
+ return: Palaa käyttäjän profiiliin
+ web: Siirry verkkosivulle
+ title: Seuraa käyttäjää %{acct}
datetime:
distance_in_words:
- about_x_hours: "%{count}t"
- about_x_months: "%{count}kk"
- about_x_years: "%{count}v"
- almost_x_years: "%{count}v"
- half_a_minute: Juuri nyt
- less_than_x_minutes: "%{count}m"
- less_than_x_seconds: Juuri nyt
- over_x_years: "%{count}v"
- x_days: "%{count}pv"
- x_minutes: "%{count}m"
- x_months: "%{count}kk"
- x_seconds: "%{count}s"
+ about_x_hours: "%{count} h"
+ about_x_months: "%{count} kk"
+ about_x_years: "%{count} v"
+ almost_x_years: "%{count} v"
+ half_a_minute: Nyt
+ less_than_x_minutes: "%{count} m"
+ less_than_x_seconds: Nyt
+ over_x_years: "%{count} v"
+ x_days: "%{count} pv"
+ x_minutes: "%{count} m"
+ x_months: "%{count} kk"
+ x_seconds: "%{count} s"
+ deletes:
+ bad_password_msg: Hyvä yritys, hakkerit! Väärä salasana
+ confirm_password: Tunnistaudu syöttämällä nykyinen salasanasi
+ description_html: Tämä poistaa pysyvästi ja peruuttamattomasti kaiken tilisi sisällön ja poistaa tilin käytöstä. Käyttäjänimesi pysyy varattuna, jotta identiteettiäsi ei myöhemmin varasteta.
+ proceed: Poista tili
+ success_msg: Tilin poisto onnistui
+ warning_html: Sisällön poistaminen taataan vain tämän instanssin osalta. Jos sisältöä on jaettu paljon, siitä todennäköisesti jää jälkiä. Palvelimet, joihin ei saada yhteyttä tai jotka ovat lopettaneet päivitystesi tilaamisen, eivät päivitä tietokantojaan.
+ warning_title: Sisällön saatavuustieto levitetty
+ errors:
+ '403': Sinulla ei ole lupaa nähdä tätä sivua.
+ '404': Etsimääsi sivua ei ole olemassa.
+ '410': Etsimääsi sivua ei ole enää olemassa.
+ '422':
+ content: Turvallisuusvahvistus epäonnistui. Oletko estänyt evästeet?
+ title: Turvallisuusvahvistus epäonnistui
+ '429': Rajoitettu
+ '500':
+ content: Valitettavasti jokin meni pieleen meidän päässämme.
+ title: Sivu ei ole oikein
+ noscript_html: Mastodon-selainsovelluksen käyttöön vaaditaan JavaScript. Voit vaihtoehtoisesti kokeilla jotakin omalle käyttöjärjestelmällesi tehtyä Mastodonsovellusta.
exports:
- blocks: Estosi
+ archive_takeout:
+ date: Päiväys
+ download: Lataa arkisto
+ hint_html: Voit pyytää arkistoa omista tuuttauksistasi ja mediastasi. Vientitiedot ovat ActivityPub-muodossa, ja ne voi lukea millä tahansa yhteensopivalla ohjelmalla.
+ in_progress: Arkistoa kootaan...
+ request: Pyydä arkisto
+ size: Koko
+ blocks: Estot
csv: CSV
follows: Seurattavat
- storage: Mediasi
+ mutes: Mykistetyt
+ storage: Media-arkisto
+ followers:
+ domain: Verkkotunnus
+ explanation_html: Jos haluat olla varma tilapäivitystesi yksityisyydestä, sinun täytyy tietää, ketkä seuraavat sinua. Yksityiset tilapäivityksesi lähetetään kaikkiin niihin instansseihin, joissa sinulla on seuraajia. Jos et luota siihen, että näiden instanssien ylläpitäjät tai ohjelmisto kunnioittavat yksityisyyttäsi, käy läpi seuraajaluettelosi ja poista tarvittaessa käyttäjiä.
+ followers_count: Seuraajien määrä
+ lock_link: Lukitse tili
+ purge: Poista seuraajista
+ success:
+ one: Estetään kevyesti seuraajia yhdestä verkkotunnuksesta...
+ other: Estetään kevyesti seuraajia %{count} verkkotunnuksesta...
+ true_privacy_html: Muista, että kunnollinen yksityisyys voidaan varmistaa vain päästä päähän -salauksella.
+ unlocked_warning_html: Kuka tahansa voi seurata sinua ja nähdä saman tien yksityiset tilapäivityksesi. %{lock_link}, niin voit tarkastaa ja torjua seuraajia.
+ unlocked_warning_title: Tiliäsi ei ole lukittu
generic:
- changes_saved_msg: Muutokset onnistuneesti tallennettu!
- powered_by: powered by %{link}
+ changes_saved_msg: Muutosten tallennus onnistui!
+ powered_by: voimanlähteenä %{link}
save_changes: Tallenna muutokset
validation_errors:
- one: Jokin ei ole viellä oikein! Katso virhe alapuolelta.
- other: Jokin ei ole viellä oikein! Katso %{count} virhettä alapuolelta.
+ one: Kaikki ei ole aivan oikein! Tarkasta alla oleva virhe
+ other: Kaikki ei ole aivan oikein! Tarkasta alla olevat %{count} virhettä
imports:
- preface: Voit tuoda tiettyä dataa kaikista ihmisistä joita seuraat tai estät tilillesi tälle palvelimelle tiedostoista, jotka on luotu toisella palvelimella.
- success: Datasi on onnistuneesti ladattu ja käsitellään pian
+ preface: Voit tuoda toisesta instanssista viemiäsi tietoja, kuten esimerkiksi seuraamiesi tai estämiesi henkilöiden listan.
+ success: Tietojen lähettäminen onnistui, ja ne käsitellään kohtapuoliin
types:
- blocking: Estetyt lista
- following: Seuratut lista
+ blocking: Estettyjen lista
+ following: Seurattujen lista
+ muting: Mykistettyjen lista
upload: Lähetä
- landing_strip_html: "%{name} on käyttäjä domainilla %{link_to_root_path}. Voit seurata tai vuorovaikuttaa heidän kanssaan jos sinulla on tili yleisessä verkossa."
- landing_strip_signup_html: Jos sinulla ei ole tiliä, voit rekisteröityä täällä.
+ in_memoriam_html: Muistoissamme.
+ invites:
+ delete: Poista käytöstä
+ expired: Vanhentunut
+ expires_in:
+ '1800': 30 minuuttia
+ '21600': 6 tuntia
+ '3600': 1 tunti
+ '43200': 12 tuntia
+ '86400': 1 vuorokausi
+ expires_in_prompt: Ei koskaan
+ generate: Luo
+ max_uses:
+ one: kertakäyttöinen
+ other: "%{count} käyttökertaa"
+ max_uses_prompt: Ei rajoitusta
+ prompt: Luo linkkejä ja jaa niiden avulla muille pääsyoikeus tähän instanssiin
+ table:
+ expires_at: Vanhenee
+ uses: Käytetty
+ title: Kutsu ihmisiä
+ landing_strip_html: "%{name} on käyttäjänä palvelimella %{link_to_root_path}. Voit seurata heitä tai pitää heihin yhteyttä, jos sinulla on tili missä tahansa fediversumin kolkassa."
+ landing_strip_signup_html: Jos sinulla ei ole tiliä, voit rekisteröityä tätä kautta.
+ lists:
+ errors:
+ limit: Sinulla on jo suurin sallittu määrä listoja
+ media_attachments:
+ validations:
+ images_and_video: Videota ei voi liittää tilapäivitykseen, jossa on jo kuvia
+ too_many: Tiedostoja voi liittää enintään 4
+ migrations:
+ acct: uuden tilin käyttäjätunnus@verkkotunnus
+ currently_redirecting: 'Profiiliisi on asetettu uudelleenohjaus:'
+ proceed: Tallenna
+ updated_msg: Tilinsiirtoasetusten päivitys onnistui!
+ moderation:
+ title: Moderointi
notification_mailer:
digest:
- body: 'Tässä on pieni yhteenveto palvelimelta %{instance} viimeksi kun olit paikalla %{since}:'
+ action: Näytä kaikki ilmoitukset
+ body: Tässä lyhyt yhteenveto viime käyntisi (%{since}) jälkeen tulleista viesteistä
mention: "%{name} mainitsi sinut:"
new_followers_summary:
- one: Olet myös saanut yhden uuden seuraajan poissaollessasi! Jee!
- other: Olet saanut %{count} uutta seuraajaa poissaollessasi! Loistavaa!
+ one: Olet myös saanut yhden uuden seuraajan! Juhuu!
+ other: Olet myös saanut %{count} uutta seuraajaa! Aivan mahtavaa!
subject:
- one: "1 uusi ilmoitus viimeisen käyntisi jälkeen \U0001F418"
- other: "%{count} uutta ilmoitusta viimeisen käyntisi jälkeen \U0001F418"
+ one: "1 uusi ilmoitus viime käyntisi jälkeen \U0001F418"
+ other: "%{count} uutta ilmoitusta viime käyntisi jälkeen \U0001F418"
+ title: Poissaollessasi…
favourite:
- body: 'Statuksestasi tykkäsi %{name}:'
- subject: "%{name} tykkäsi sinun statuksestasi"
+ body: "%{name} tykkäsi tilastasi:"
+ subject: "%{name} tykkäsi tilastasi"
+ title: Uusi tykkäys
follow:
body: "%{name} seuraa nyt sinua!"
subject: "%{name} seuraa nyt sinua"
+ title: Uusi seuraaja
follow_request:
- body: "%{name} on pyytänyt seurata sinua"
- subject: 'Odottava seuraus pyyntö: %{name}'
+ action: Hallinnoi seuraamispyyntöjä
+ body: "%{name} haluaa seurata sinua"
+ subject: 'Odottava seuraamispyyntö: %{name}'
+ title: Uusi seuraamispyyntö
mention:
- body: 'Sinut mainitsi %{name} postauksessa:'
- subject: Sinut mainitsi %{name}
+ action: Vastaa
+ body: "%{name} mainitsi sinut:"
+ subject: "%{name} mainitsi sinut"
+ title: Uusi maininta
reblog:
- body: 'Sinun statustasi boostasi %{name}:'
- subject: "%{name} boostasi statustasi"
+ body: "%{name} buustasi tilaasi:"
+ subject: "%{name} boostasi tilaasi"
+ title: Uusi buustaus
number:
human:
decimal_units:
- format: "%n%u"
+ format: "%n %u"
units:
- billion: B
+ billion: Mrd
million: M
- quadrillion: Q
- thousand: K
- trillion: T
+ quadrillion: Brd
+ thousand: k
+ trillion: B
unit: ''
pagination:
+ newer: Uudemmat
next: Seuraava
+ older: Vanhemmat
prev: Edellinen
+ truncate: "…"
+ preferences:
+ languages: Kielet
+ other: Muut
+ publishing: Julkaiseminen
+ web: Web
+ push_notifications:
+ favourite:
+ title: "%{name} tykkäsi tilastasi"
+ follow:
+ title: "%{name} seuraa nyt sinua"
+ group:
+ title: "%{count} ilmoitusta"
+ mention:
+ action_boost: Buustaa
+ action_expand: Näytä lisää
+ action_favourite: Tykkää
+ title: "%{nimi} mainitsi sinut"
+ reblog:
+ title: "%{name} buustasi tilaasi"
remote_follow:
- acct: Syötä sinun käyttäjänimesi@domain jos haluat seurata palvelimelta
- missing_resource: Ei löydetty tarvittavaa uudelleenohjaavaa URL-linkkiä tilillesi
- proceed: Siirry seuraamiseen
- prompt: 'Sinä aiot seurata:'
+ acct: Syötä se käyttäjätunnus@verkkotunnus, josta haluat seurata
+ missing_resource: Vaadittavaa uudelleenohjaus-URL:ää tiliisi ei löytynyt
+ proceed: Siirry seuraamaan
+ prompt: 'Olet aikeissa seurata:'
+ sessions:
+ activity: Viimeisin toiminta
+ browser: Selain
+ browsers:
+ alipay: Alipay
+ blackberry: Blackberry
+ chrome: Chrome
+ edge: Microsoft Edge
+ electron: Electron
+ firefox: Firefox
+ generic: Tuntematon selain
+ ie: Internet Explorer
+ micro_messenger: MicroMessenger
+ nokia: Nokia S40 Ovi -selain
+ opera: Opera
+ otter: Otter
+ phantom_js: PhantomJS
+ qq: QQ Browser
+ safari: Safari
+ uc_browser: UCBrowser
+ weibo: Weibo
+ current_session: Nykyinen istunto
+ description: "%{selain}, %{platform}"
+ explanation: Nämä verkkoselaimet ovat tällä hetkellä kirjautuneet Mastodon-tilillesi.
+ ip: IP
+ platforms:
+ adobe_air: Adobe Air
+ android: Android
+ blackberry: Blackberry
+ chrome_os: ChromeOS
+ firefox_os: Firefox OS
+ ios: iOS
+ linux: Linux
+ mac: Mac
+ other: tuntematon järjestelmä
+ windows: Windows
+ windows_mobile: Windows Mobile
+ windows_phone: Windows Phone
+ revoke: Hylkää
+ revoke_success: Istunnon hylkäys onnistui
+ title: Istunnot
settings:
- authorized_apps: Valtuutetut ohjelmat
+ authorized_apps: Valtuutetut sovellukset
back: Takaisin Mastodoniin
+ delete: Tilin poisto
+ development: Kehittäminen
edit_profile: Muokkaa profiilia
- export: Vie dataa
- import: Tuo dataa
+ export: Vie tietoja
+ followers: Valtuutetut seuraajat
+ import: Tuo
+ migrate: Tilin muutto muualle
+ notifications: Ilmoitukset
preferences: Ominaisuudet
settings: Asetukset
- two_factor_authentication: Kaksivaiheinen tunnistus
+ two_factor_authentication: Kaksivaiheinen todentaminen
+ your_apps: Omat sovellukset
statuses:
- open_in_web: Avaa webissä
- over_character_limit: sallittu kirjanmäärä %{max} ylitetty
+ attached:
+ description: 'Liitetty: %{attached}'
+ image:
+ one: "%{count} kuva"
+ other: "%{count} kuvaa"
+ video:
+ one: "%{count} video"
+ other: "%{count} videota"
+ content_warning: 'Sisältövaroitus: %{warning}'
+ open_in_web: Avaa selaimessa
+ over_character_limit: merkkimäärän rajoitus %{max} ylitetty
+ pin_errors:
+ limit: Olet jo kiinnittänyt suurimman mahdollisen määrän tuuttauksia
+ ownership: Muiden tuuttauksia ei voi kiinnittää
+ private: Piilotettua tuuttausta ei voi kiinnittää
+ reblog: Buustausta ei voi kiinnittää
show_more: Näytä lisää
+ title: "%{name}: ”%{quote}”"
visibilities:
- private: Näytä vain seuraajille
+ private: Vain seuraajille
+ private_long: Näytä vain seuraajille
public: Julkinen
- unlisted: Julkinen, mutta älä näytä julkisella aikajanalla
+ public_long: Kaikki voivat nähdä
+ unlisted: Listaamaton julkinen
+ unlisted_long: Kaikki voivat nähdä, mutta ei näytetä julkisilla aikajanoilla
stream_entries:
- click_to_show: Klikkaa näyttääksesi
- reblogged: boosted
- sensitive_content: Herkkä materiaali
+ click_to_show: Katso napsauttamalla
+ pinned: Kiinnitetty tuuttaus
+ reblogged: buustasi
+ sensitive_content: Arkaluontoista sisältöä
+ terms:
+ title: "%{instance}, käyttöehdot ja tietosuojakäytäntö"
+ themes:
+ default: Mastodon
time:
formats:
- default: "%b %d, %Y, %H:%M"
+ default: "%d.%m.%Y klo %H.%M"
two_factor_authentication:
- description_html: Jos otat käyttöön kaksivaiheisen tunnistuksen, kirjautumiseen vaaditaan puhelin, joka voi luoda tokeneita kirjautumista varten.
+ code_hint: Vahvista syöttämällä todentamissovelluksen generoima koodi
+ description_html: Jos otat käyttöön kaksivaiheisen todentamisen, kirjautumiseen vaaditaan puhelin, jolla voidaan luoda kirjautumistunnuksia.
disable: Poista käytöstä
enable: Ota käyttöön
- instructions_html: "Skannaa tämä QR-koodi Google Authenticator- tai vastaavaan sovellukseen puhelimellasi. Tästä hetkestä lähtien ohjelma luo koodin, mikä sinun tarvitsee syöttää sisäänkirjautuessa."
+ enabled: Kaksivaiheinen todentaminen käytössä
+ enabled_success: Kaksivaiheisen todentamisen käyttöönotto onnistui
+ generate_recovery_codes: Luo palautuskoodit
+ instructions_html: "Lue tämä QR-koodi puhelimen Google Authenticator- tai vastaavalla TOTP-sovelluksella. Sen jälkeen sovellus luo tunnuksia, joita tarvitset sisäänkirjautuessasi."
+ lost_recovery_codes: Palautuskoodien avulla voit käyttää tiliä, jos menetät puhelimesi. Jos olet hukannut palautuskoodit, voit luoda uudet tästä. Vanhat palautuskoodit poistetaan käytöstä.
+ manual_instructions: 'Jos et voi lukea QR-koodia ja haluat syöttää sen käsin, tässä on salainen koodi tekstinä:'
+ recovery_codes: Varapalautuskoodit
+ recovery_codes_regenerated: Uusien palautuskoodien luonti onnistui
+ recovery_instructions_html: Jos menetät puhelimesi, voit kirjautua tilillesi jollakin alla olevista palautuskoodeista. Pidä palautuskoodit hyvässä tallessa. Voit esimerkiksi tulostaa ne ja säilyttää muiden tärkeiden papereiden joukossa.
+ setup: Ota käyttöön
+ wrong_code: Annettu koodi oli virheellinen! Ovatko palvelimen aika ja laitteen aika oikein?
+ user_mailer:
+ backup_ready:
+ explanation: Pyysit täydellistä varmuuskopiota Mastodon-tilistäsi. Voit nyt ladata sen!
+ subject: Arkisto on valmiina ladattavaksi
+ title: Arkiston tallennus
+ welcome:
+ edit_profile_action: Aseta profiili
+ edit_profile_step: Voit mukauttaa profiiliasi lataamalla profiilikuvan ja otsakekuvan, muuttamalla näyttönimeäsi ym. Jos haluat hyväksyä uudet seuraajat ennen kuin he voivat seurata sinua, voit lukita tilisi.
+ explanation: Näillä vinkeillä pääset alkuun
+ final_action: Ala julkaista
+ final_step: 'Ala julkaista! Vaikkei sinulla olisi seuraajia, monet voivat nähdä julkiset viestisi esimerkiksi paikallisella aikajanalla ja hashtagien avulla. Kannattaa esittäytyä! Käytä hashtagia #introductions. (Jos haluat esittäytyä myös suomeksi, se kannattaa tehdä erillisessä tuuttauksessa ja käyttää hashtagia #esittely.)'
+ full_handle: Koko käyttäjätunnuksesi
+ full_handle_hint: Kerro tämä ystävillesi, niin he voivat lähettää sinulle viestejä tai löytää sinut toisen instanssin kautta.
+ review_preferences_action: Muuta asetuksia
+ review_preferences_step: Käy tarkistamassa, että asetukset ovat haluamallasi tavalla. Voit valita, missä tilanteissa haluat saada sähköpostia, mikä on julkaisujesi oletusnäkyvyys jne. Jos et saa helposti pahoinvointia, voit valita, että GIF-animaatiot toistetaan automaattisesti.
+ subject: Tervetuloa Mastodoniin
+ tip_bridge_html: Jos tulet Twitteristä, voit etsiä ystäviäsi Mastodonista siltasovelluksen avulla. Se kuitenkin löytää heidät vain, jos hekin käyttävät sitä!
+ tip_federated_timeline: Yleinen aikajana näyttää sisältöä koko Mastodon-verkostosta. Siinä näkyvät kuitenkin vain ne henkilöt, joita oman instanssisi käyttäjät seuraavat. Siinä ei siis näytetä aivan kaikkea.
+ tip_following: Oletusarvoisesti seuraat oman palvelimesi ylläpitäjiä. Etsi lisää kiinnostavia ihmisiä paikalliselta ja yleiseltä aikajanalta.
+ tip_local_timeline: Paikallinen aikajana näyttää instanssin %{instance} käyttäjien julkaisut. He ovat naapureitasi!
+ tip_mobile_webapp: Jos voit lisätä Mastodonin mobiiliselaimen kautta aloitusnäytöllesi, voit vastaanottaa push-ilmoituksia. Toiminta vastaa monin tavoin tavanomaista sovellusta!
+ tips: Vinkkejä
+ title: Tervetuloa mukaan, %name}!
users:
- invalid_email: Virheellinen sähköposti
- invalid_otp_token: Virheellinen kaksivaihetunnistuskoodi
+ invalid_email: Virheellinen sähköpostiosoite
+ invalid_otp_token: Virheellinen kaksivaiheisen todentamisen koodi
+ seamless_external_login: Olet kirjautunut ulkoisen palvelun kautta, joten salasana- ja sähköpostiasetukset eivät ole käytettävissä.
+ signed_in_as: 'Kirjautunut henkilönä:'
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 960dd38ef..fecf996d5 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -18,7 +18,7 @@ ja:
features:
humane_approach_body: 他の SNS の失敗から学び、Mastodon はソーシャルメディアが誤った使い方をされることの無いように倫理的な設計を目指しています。
humane_approach_title: より思いやりのある設計
- not_a_product_body: Mastodon は営利的な SNS ではありません。広告や、データの収集・解析は無く、またユーザーの囲い込みもありません。
+ not_a_product_body: Mastodon は営利的な SNS ではありません。広告や、データの収集・解析は無く、またユーザーの囲い込みもありません。ここには中央権力はありません。
not_a_product_title: あなたは人間であり、商品ではありません
real_conversation_body: 好きなように書ける500文字までの投稿や、文章やメディアの内容に警告をつけられる機能で、思い通りに自分自身を表現することができます。
real_conversation_title: 本当のコミュニケーションのために
diff --git a/config/locales/simple_form.eo.yml b/config/locales/simple_form.eo.yml
index 17862f916..41a0c26aa 100644
--- a/config/locales/simple_form.eo.yml
+++ b/config/locales/simple_form.eo.yml
@@ -14,7 +14,7 @@ eo:
one: 1 signo restas
other: %{count} signoj restas
setting_noindex: Influas vian publikan profilon kaj mesaĝajn paĝojn
- setting_theme: Influas kiel Mastodon aspektas kiam vi ensalutis en ajna aparato.
+ setting_theme: Influas kiel Mastodon aspektas post ensaluto de ajna aparato.
imports:
data: CSV-dosiero el alia nodo de Mastodon
sessions:
@@ -45,7 +45,7 @@ eo:
setting_default_privacy: Mesaĝa videbleco
setting_default_sensitive: Ĉiam marki aŭdovidaĵojn tiklaj
setting_delete_modal: Montri fenestron por konfirmi antaŭ ol forigi mesaĝon
- setting_display_sensitive_media: Ĉiam montri aŭdovidaĵon markitajn tiklaj
+ setting_display_sensitive_media: Ĉiam montri aŭdovidaĵojn markitajn tiklaj
setting_noindex: Ellistiĝi de retserĉila indeksado
setting_reduce_motion: Malrapidigi animaciojn
setting_system_font_ui: Uzi la dekomencan tiparon de la sistemo
diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml
index 34605c4f6..f48e9ab23 100644
--- a/config/locales/simple_form.fi.yml
+++ b/config/locales/simple_form.fi.yml
@@ -3,64 +3,68 @@ fi:
simple_form:
hints:
defaults:
- avatar: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 400x400px
- digest: Lähetetään vain pitkän poissaolon jälkeen, ja vain jos olet vastaanottanut yksityisviestejä poissaolosi aikana
- display_name: Korkeintaan 30 merkkiä
- header: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 700x335px
- locked: Vaatii sinua manuaalisesti hyväksymään seuraajat
- note: Korkeintaan 160 merkkiä
- setting_noindex: Vaikuttaa julkiseen profiiliisi ja statuspäivityksiisi
- setting_theme: Vaikuttaa siihen, miltä Mastodon näyttää kun olet kirjautuneena milllä tahansa laitteella.
+ avatar: PNG, GIF tai JPG. Enintään 2 Mt. Skaalataan kokoon 400 x 400 px
+ digest: Lähetetään vain pitkän poissaolon jälkeen ja vain, jos olet saanut suoria viestejä poissaolosi aikana
+ display_name:
+ one: 1 merkki jäljellä
+ other: %{count} merkkiä jäljellä
+ header: PNG, GIF tai JPG. Enintään 2 Mt. Skaalataan kokoon 700 x 335 px
+ locked: Sinun täytyy hyväksyä seuraajat manuaalisesti
+ note:
+ one: 1 merkki jäljellä
+ other: %{count} merkkiä jäljellä
+ setting_noindex: Vaikuttaa julkiseen profiiliisi ja tilasivuihisi
+ setting_theme: Vaikuttaa Mastodonin ulkoasuun millä tahansa laitteella kirjauduttaessa.
imports:
- data: CSV tiedosto, joka on tuotu toiselta Mastodon-palvelimelta
+ data: Toisesta Mastodon-instanssista tuotu CSV-tiedosto
sessions:
- otp: Syötä kaksivaiheisen tunnistuksen koodi puhelimestasi tai käytä yhtä palautuskoodeistasi.
+ otp: Syötä puhelimeen saamasi kaksivaiheisen tunnistautumisen koodi tai käytä palautuskoodia.
user:
- filtered_languages: Valitut kielet suodatetaan julkisilta aikajanoilta
+ filtered_languages: Valitut kielet suodatetaan pois julkisilta aikajanoilta
labels:
defaults:
avatar: Profiilikuva
- confirm_new_password: Varmista uusi salasana
- confirm_password: Varmista salasana
+ confirm_new_password: Vahvista uusi salasana
+ confirm_password: Vahvista salasana
current_password: Nykyinen salasana
- data: Data
+ data: Tiedot
display_name: Nimimerkki
email: Sähköpostiosoite
- expires_in: Vanhentuu
+ expires_in: Vanhenee
filtered_languages: Suodatetut kielet
header: Otsakekuva
locale: Kieli
- locked: Tee tilistä yksityinen
- max_uses: Max käyttökerrat
+ locked: Lukitse tili
+ max_uses: Käyttökertoja enintään
new_password: Uusi salasana
note: Kuvaus
- otp_attempt: Kaksivaiheinen koodi
+ otp_attempt: Kaksivaiheisen tunnistautumisen koodi
password: Salasana
- setting_auto_play_gif: Animoitujen GIFfien automaattitoisto
- setting_boost_modal: Näytä vahvistusikkuna ennen boostausta
- setting_default_privacy: Julkaisun yksityisyys
+ setting_auto_play_gif: Toista GIF-animaatiot automaattisesti
+ setting_boost_modal: Kysy vahvistusta ennen buustausta
+ setting_default_privacy: Julkaisun näkyvyys
setting_default_sensitive: Merkitse media aina arkaluontoiseksi
- setting_delete_modal: Näytä vahvistusikkuna ennen töötin poistamista
+ setting_delete_modal: Kysy vahvistusta ennen tuuttauksen poistamista
setting_display_sensitive_media: Näytä aina arkaluontoiseksi merkitty media
setting_noindex: Jättäydy pois hakukoneindeksoinnista
- setting_reduce_motion: Vähennä liikettä animaatioissa
- setting_system_font_ui: Käytä käyttöjärjestelmän oletusfonttia
+ setting_reduce_motion: Vähennä animaatioiden liikettä
+ setting_system_font_ui: Käytä järjestelmän oletusfonttia
setting_theme: Sivuston teema
- setting_unfollow_modal: Näytä vahvistusikkuna ennen seuraamisen lopettamista
- severity: Vakavuusaste
- type: Tuontityyppi
+ setting_unfollow_modal: Kysy vahvistusta, ennen kuin lopetat seuraamisen
+ severity: Vakavuus
+ type: Tietojen laji
username: Käyttäjänimi
username_or_email: Käyttäjänimi tai sähköposti
interactions:
must_be_follower: Estä ilmoitukset käyttäjiltä, jotka eivät seuraa sinua
must_be_following: Estä ilmoitukset käyttäjiltä, joita et seuraa
- must_be_following_dm: Estä suorat viestit ihmisiltä, joita et seuraa
+ must_be_following_dm: Estä suorat viestit käyttäjiltä, joita et seuraa
notification_emails:
- digest: Lähetä koosteviestejä sähköpostilla
- favourite: Lähetä sähköposti, kun joku tykkää statuksestasi
+ digest: Lähetä koosteviestejä sähköpostitse
+ favourite: Lähetä sähköposti, kun joku tykkää tilastasi
follow: Lähetä sähköposti, kun joku seuraa sinua
follow_request: Lähetä sähköposti, kun joku pyytää seurata sinua
- mention: Lähetä sähköposti, kun joku mainitsee sinut
+ mention: Lähetä sähköposti, kun sinut mainitaan
reblog: Lähetä sähköposti, kun joku buustaa julkaisusi
'no': Ei
required:
diff --git a/config/locales/simple_form.sk.yml b/config/locales/simple_form.sk.yml
index 7d4241bac..e504c9774 100644
--- a/config/locales/simple_form.sk.yml
+++ b/config/locales/simple_form.sk.yml
@@ -6,21 +6,21 @@ sk:
avatar: PNG, GIF alebo JPG. Maximálne 2MB. Bude zmenšený na 400x400px
digest: Odoslané iba v prípade dlhodobej neprítomnosti, a len ak ste obdŕžali nejaké osobné správy kým ste boli preč
display_name:
- one: Ostáva vám 1 znak
- other: Ostáva vám %{count} znakov
+ one: Ostáva ti 1 znak
+ other: Ostáva ti %{count} znakov
header: PNG, GIF alebo JPG. Maximálne 2MB. Bude zmenšený na 700x335px
locked: Musíte manuálne schváliť sledujúcich
note:
one: Ostáva vám 1 znak
- other: Ostáva vám %{count}znakov
- setting_noindex: Ovplyvňuje profil a správy tak, že ich nebude možné nájsť vyhľadávaním
- setting_theme: Ovplyvní ako bude Mastodon vyzerať pri prihlásení z hociktorého zariadenia.
+ other: Ostáva ti %{count} znakov
+ setting_noindex: Ovplyvňuje profil a správy tak, že ich nebude možné nájsť vyhľadávaním
+ setting_theme: Toto ovplyvní ako bude Mastodon vyzerať pri prihlásení z hociktorého zariadenia.
imports:
data: CSV súbor vyexportovaný z inej Mastodon inštancie
sessions:
- otp: Vložte 2FA kód z telefónu alebo použite jeden z vašich obnovovacích kódov.
+ otp: Napíš sem dvoj-faktorový kód z telefónu, alebo použite jeden z vašich obnovovacích kódov.
user:
- filtered_languages: Zaškrtnuté jazyky vám nebudú zobrazené vo verejnej časovej osi
+ filtered_languages: Zaškrtnuté jazyky budú pre teba vynechané nebudú z verejnej časovej osi
labels:
defaults:
avatar: Avatar
@@ -53,7 +53,7 @@ sk:
setting_unfollow_modal: Zobrazovať potvrdzovacie okno pred skončením sledovania iného používateľa
severity: Závažnosť
type: Typ importu
- username: Používateľské meno
+ username: Užívateľské meno
username_or_email: Prezívka, alebo Email
interactions:
must_be_follower: Blokovať notifikácie pod používateľov, ktorí ťa nesledujú
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 2ee25b372..25e672604 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -149,15 +149,15 @@ sk:
enable_custom_emoji: "%{name} povolil emoji %{target}"
enable_user: "%{name} povolil prihlásenie pre používateľa %{target}"
memorialize_account: '%{name} zmenil účet %{target} na stránku "Navždy budeme spomínať"'
- promote_user: "%{name} povýšil používateľa %{target}"
- reset_password_user: "%{name} resetoval heslo pre používateľa %{target}"
- resolve_report: "%{name} zamietol nahlásenie %{target}"
- silence_account: "%{name} stíšil účet %{target}"
- suspend_account: "%{name} suspendoval účet používateľa %{target}"
- unsilence_account: "%{name} zrušil stíšenie účtu používateľa %{target}"
- unsuspend_account: "%{name} zrušil suspendáciu účtu používateľa %{target}"
- update_custom_emoji: "%{name} aktualizoval emoji %{target}"
- update_status: "%{name} aktualizoval status %{target}"
+ promote_user: "%{name} povýšil/a používateľa %{target}"
+ reset_password_user: "%{name} resetoval/a heslo pre používateľa %{target}"
+ resolve_report: "%{name} zamietli nahlásenie %{target}"
+ silence_account: "%{name} utíšil/a účet %{target}"
+ suspend_account: "%{name} zablokoval/a účet používateľa %{target}"
+ unsilence_account: "%{name} zrušil/a utíšenie účtu používateľa %{target}"
+ unsuspend_account: "%{name} zrušil/a blokovanie účtu používateľa %{target}"
+ update_custom_emoji: "%{name} aktualizoval/a emoji %{target}"
+ update_status: "%{name} aktualizoval/a status pre %{target}"
title: Kontrólny záznam
custom_emojis:
by_domain: Doména
@@ -358,7 +358,7 @@ sk:
warning: Na tieto údaje dávajte ohromný pozor. Nikdy ich s nikým nezďieľajte!
your_token: Váš prístupový token
auth:
- agreement_html: V rámci registrácie súhlasíte, že sa budete riadiť 1 pravidlami tejto instancie 2 a taktiež 3 našími servisnými podmienkami 4.
+ agreement_html: V rámci registrácie súhlasíš, že sa budeš riadiť pravidlami tejto instancie, a taktiež našími servisnými podmienkami .
change_password: Heslo
confirm_email: Potvrdiť email
delete_account: Vymazať účet
@@ -366,8 +366,8 @@ sk:
didnt_get_confirmation: Neobdŕžali ste kroky pre potvrdenie?
forgot_password: Zabudli ste heslo?
invalid_reset_password_token: Token na obnovu hesla vypršal. Prosím vypítajte si nový.
- login: Prihlásenie
- logout: Odhlásiť sa
+ login: Prihlás sa
+ logout: Odhlás sa
migrate_account: Presunúť sa na iný účet
migrate_account_html: Pokiaľ si želáte presmerovať tento účet na nejaký iný, môžete tak urobiť tu.
or: alebo
@@ -375,7 +375,7 @@ sk:
providers:
cas: CAS
saml: SAML
- register: Zaregistrovať sa
+ register: Zaregistruj sa
register_elsewhere: Zaregistruj sa na inom serveri
resend_confirmation: Poslať potvrdzujúce pokyny znovu
reset_password: Resetovať heslo
@@ -677,6 +677,7 @@ sk:
full_handle: Adresa tvojho profilu v celom formáte
full_handle_hint: Toto je čo musíš dať vedieť svojím priateľom aby ti mohli posielať správy, alebo ťa následovať z inej instancie.
review_preferences_action: Zmeniť nastavenia
+ review_preferences_step: Daj si záležať na svojích nastaveniach, napríklad že aké emailové notifikácie chceš dostávať, alebo pod aký level súkromia sa tvoje príspevky majú sami automaticky zaradiť. Pokiaľ nemáš malátnosť z pohybu, môžeš si zvoliť aj automatické spúšťanie GIF animácií.
subject: Vitaj na Mastodone
tip_bridge_html: Ak prichádzaš z Twitteru, môžeš svojích priateľov nájsť na Mastodone pomocou tzv. mostíkovej aplikácie. Ale tá funguje iba ak ju aj oni niekedy použili!
tip_federated_timeline: Federovaná os zobrazuje sieť Mastodonu až po jej hranice. Ale zahŕňa iba ľúdí ktorých ostatní okolo teba sledujú, takže predsa nieje úplne celistvá.
From a1049e93807f57796eb6229f2dd1388be8b18225 Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Mon, 16 Apr 2018 17:04:31 +0900
Subject: [PATCH 081/442] Redirect to account status page for page of status
stream entry (#7104)
Commit 519119f657cf97ec187008a28dba00c1125a9292 missed a change for
stream entry page. Instead of duplicating the change, redirect to account
status page. It would also help crawlers (of search engines, for example)
to understand a stream entry URL and its corresponding status URL points
to the same page.
---
app/controllers/stream_entries_controller.rb | 3 +--
spec/controllers/stream_entries_controller_spec.rb | 10 +++-------
2 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/app/controllers/stream_entries_controller.rb b/app/controllers/stream_entries_controller.rb
index f81856cc6..97cf85079 100644
--- a/app/controllers/stream_entries_controller.rb
+++ b/app/controllers/stream_entries_controller.rb
@@ -15,8 +15,7 @@ class StreamEntriesController < ApplicationController
def show
respond_to do |format|
format.html do
- @ancestors = @stream_entry.activity.reply? ? cache_collection(@stream_entry.activity.ancestors(current_account), Status) : []
- @descendants = cache_collection(@stream_entry.activity.descendants(current_account), Status)
+ redirect_to short_account_status_url(params[:account_username], @stream_entry.activity) if @type == 'status'
end
format.atom do
diff --git a/spec/controllers/stream_entries_controller_spec.rb b/spec/controllers/stream_entries_controller_spec.rb
index f81e2be7b..665c5b747 100644
--- a/spec/controllers/stream_entries_controller_spec.rb
+++ b/spec/controllers/stream_entries_controller_spec.rb
@@ -66,16 +66,12 @@ RSpec.describe StreamEntriesController, type: :controller do
describe 'GET #show' do
include_examples 'before_action', :show
- it 'renders with HTML' do
- ancestor = Fabricate(:status)
- status = Fabricate(:status, in_reply_to_id: ancestor.id)
- descendant = Fabricate(:status, in_reply_to_id: status.id)
+ it 'redirects to status page' do
+ status = Fabricate(:status)
get :show, params: { account_username: status.account.username, id: status.stream_entry.id }
- expect(assigns(:ancestors)).to eq [ancestor]
- expect(assigns(:descendants)).to eq [descendant]
- expect(response).to have_http_status(:success)
+ expect(response).to redirect_to(short_account_status_url(status.account, status))
end
it 'returns http success with Atom' do
From 1a37d7e252aa41fd1c66e780e1a2a1426d8f3545 Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Mon, 16 Apr 2018 18:34:34 +0900
Subject: [PATCH 082/442] Fix status filtering in contexts reducer (#7149)
---
app/javascript/mastodon/reducers/contexts.js | 38 +++++++++++---------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/app/javascript/mastodon/reducers/contexts.js b/app/javascript/mastodon/reducers/contexts.js
index fe8308d0c..c1ecf7e8a 100644
--- a/app/javascript/mastodon/reducers/contexts.js
+++ b/app/javascript/mastodon/reducers/contexts.js
@@ -21,24 +21,30 @@ const normalizeContext = (state, id, ancestors, descendants) => {
});
};
-const deleteFromContexts = (state, id) => {
- state.getIn(['descendants', id], ImmutableList()).forEach(descendantId => {
- state = state.updateIn(['ancestors', descendantId], ImmutableList(), list => list.filterNot(itemId => itemId === id));
- });
+const deleteFromContexts = (immutableState, ids) => immutableState.withMutations(state => {
+ state.update('ancestors', immutableAncestors => immutableAncestors.withMutations(ancestors => {
+ state.update('descendants', immutableDescendants => immutableDescendants.withMutations(descendants => {
+ ids.forEach(id => {
+ descendants.get(id, ImmutableList()).forEach(descendantId => {
+ ancestors.update(descendantId, ImmutableList(), list => list.filterNot(itemId => itemId === id));
+ });
- state.getIn(['ancestors', id], ImmutableList()).forEach(ancestorId => {
- state = state.updateIn(['descendants', ancestorId], ImmutableList(), list => list.filterNot(itemId => itemId === id));
- });
+ ancestors.get(id, ImmutableList()).forEach(ancestorId => {
+ descendants.update(ancestorId, ImmutableList(), list => list.filterNot(itemId => itemId === id));
+ });
- state = state.deleteIn(['descendants', id]).deleteIn(['ancestors', id]);
+ descendants.delete(id);
+ ancestors.delete(id);
+ });
+ }));
+ }));
+});
- return state;
-};
+const filterContexts = (state, relationship, statuses) => {
+ const ownedStatusIds = statuses.filter(status => status.get('account') === relationship.id)
+ .map(status => status.get('id'));
-const filterContexts = (state, relationship) => {
- return state.map(
- statuses => statuses.filter(
- status => status.get('account') !== relationship.id));
+ return deleteFromContexts(state, ownedStatusIds);
};
const updateContext = (state, status, references) => {
@@ -61,11 +67,11 @@ export default function contexts(state = initialState, action) {
switch(action.type) {
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
- return filterContexts(state, action.relationship);
+ return filterContexts(state, action.relationship, action.statuses);
case CONTEXT_FETCH_SUCCESS:
return normalizeContext(state, action.id, action.ancestors, action.descendants);
case TIMELINE_DELETE:
- return deleteFromContexts(state, action.id);
+ return deleteFromContexts(state, [action.id]);
case TIMELINE_CONTEXT_UPDATE:
return updateContext(state, action.status, action.references);
default:
From 1c379b7ef46edeaa7a8238902546ed7215b02fe2 Mon Sep 17 00:00:00 2001
From: ThibG
Date: Mon, 16 Apr 2018 17:19:04 +0200
Subject: [PATCH 083/442] Remove extra spaces from search API queries and
public account headers (fixes #7129) (#7152)
---
app/services/search_service.rb | 2 +-
app/views/accounts/_header.html.haml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 00a8b3dd7..5bb395942 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -4,7 +4,7 @@ class SearchService < BaseService
attr_accessor :query, :account, :limit, :resolve
def call(query, limit, resolve = false, account = nil)
- @query = query
+ @query = query.strip
@account = account
@limit = limit
@resolve = resolve
diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml
index 0d3a0d08d..f246f5326 100644
--- a/app/views/accounts/_header.html.haml
+++ b/app/views/accounts/_header.html.haml
@@ -6,8 +6,8 @@
.card__bio
%h1.name
%span.p-name.emojify= display_name(account)
- %small
- %span @#{account.local_username_and_domain}
+ %small<
+ %span>< @#{account.local_username_and_domain}
= fa_icon('lock') if account.locked?
- if Setting.show_staff_badge
From 7e0aed398f7e3e74a3c15e426082f88cf8b79bcf Mon Sep 17 00:00:00 2001
From: ThibG
Date: Mon, 16 Apr 2018 21:04:24 +0200
Subject: [PATCH 084/442] Fix scrolling behavior (#7151)
* Update React.JS
* Use React's new lifecycles for scrollable lists
* Clean up dead code
* Make CodeClimate happy
---
.../mastodon/components/scrollable_list.js | 32 +++++++------------
package.json | 4 +--
2 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js
index ee07106f7..fd6858d05 100644
--- a/app/javascript/mastodon/components/scrollable_list.js
+++ b/app/javascript/mastodon/components/scrollable_list.js
@@ -34,7 +34,7 @@ export default class ScrollableList extends PureComponent {
};
state = {
- lastMouseMove: null,
+ fullscreen: null,
};
intersectionObserverWrapper = new IntersectionObserverWrapper();
@@ -43,7 +43,6 @@ export default class ScrollableList extends PureComponent {
if (this.node) {
const { scrollTop, scrollHeight, clientHeight } = this.node;
const offset = scrollHeight - scrollTop - clientHeight;
- this._oldScrollPosition = scrollHeight - scrollTop;
if (400 > offset && this.props.onLoadMore && !this.props.isLoading) {
this.props.onLoadMore();
@@ -59,14 +58,6 @@ export default class ScrollableList extends PureComponent {
trailing: true,
});
- handleMouseMove = throttle(() => {
- this._lastMouseMove = new Date();
- }, 300);
-
- handleMouseLeave = () => {
- this._lastMouseMove = null;
- }
-
componentDidMount () {
this.attachScrollListener();
this.attachIntersectionObserver();
@@ -76,21 +67,26 @@ export default class ScrollableList extends PureComponent {
this.handleScroll();
}
- componentDidUpdate (prevProps) {
+ getSnapshotBeforeUpdate (prevProps) {
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) {
+ return this.node.scrollHeight - this.node.scrollTop;
+ } else {
+ return null;
+ }
+ }
+ componentDidUpdate (prevProps, prevState, snapshot) {
// Reset the scroll position when a new child comes in in order not to
// jerk the scrollbar around if you're already scrolled down the page.
- if (someItemInserted && this._oldScrollPosition && this.node.scrollTop > 0) {
- const newScrollTop = this.node.scrollHeight - this._oldScrollPosition;
+ if (snapshot !== null) {
+ const newScrollTop = this.node.scrollHeight - snapshot;
if (this.node.scrollTop !== newScrollTop) {
this.node.scrollTop = newScrollTop;
}
- } else {
- this._oldScrollPosition = this.node.scrollHeight - this.node.scrollTop;
}
}
@@ -143,10 +139,6 @@ export default class ScrollableList extends PureComponent {
this.props.onLoadMore();
}
- _recentlyMoved () {
- return this._lastMouseMove !== null && ((new Date()) - this._lastMouseMove < 600);
- }
-
render () {
const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, emptyMessage, onLoadMore } = this.props;
const { fullscreen } = this.state;
@@ -157,7 +149,7 @@ export default class ScrollableList extends PureComponent {
if (isLoading || childrenCount > 0 || !emptyMessage) {
scrollableArea = (
-
+
{prepend}
diff --git a/package.json b/package.json
index 9858d28d4..75e9e9f6d 100644
--- a/package.json
+++ b/package.json
@@ -83,8 +83,8 @@
"prop-types": "^15.5.10",
"punycode": "^2.1.0",
"rails-ujs": "^5.1.2",
- "react": "^16.2.0",
- "react-dom": "^16.2.0",
+ "react": "^16.3.0",
+ "react-dom": "^16.3.0",
"react-hotkeys": "^0.10.0",
"react-immutable-proptypes": "^2.1.0",
"react-immutable-pure-component": "^1.1.1",
From 3c722fe687de0c6e6ba144a8c87c34465fca3af9 Mon Sep 17 00:00:00 2001
From: Remi Rampin
Date: Tue, 17 Apr 2018 04:37:51 +0200
Subject: [PATCH 085/442] Update French javascript locale file (#7165)
Match config/locales/fr.yml: "private" was changed to "followers-only"
by 501514960a9de238e23cd607d2e8f4c1ff9f16c1.
---
app/javascript/mastodon/locales/fr.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index e340fda9e..ef1c115e3 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -205,8 +205,8 @@
"privacy.change": "Ajuster la confidentialité du message",
"privacy.direct.long": "N'envoyer qu'aux personnes mentionnées",
"privacy.direct.short": "Direct",
- "privacy.private.long": "N'envoyer qu'à vos abonné⋅e⋅s",
- "privacy.private.short": "Privé",
+ "privacy.private.long": "Seul⋅e⋅s vos abonné⋅e⋅s verront vos statuts",
+ "privacy.private.short": "Abonné⋅e⋅s uniquement",
"privacy.public.long": "Afficher dans les fils publics",
"privacy.public.short": "Public",
"privacy.unlisted.long": "Ne pas afficher dans les fils publics",
From 609bf9302976768c56116f9d920f34a430d538b5 Mon Sep 17 00:00:00 2001
From: abcang
Date: Tue, 17 Apr 2018 20:49:09 +0900
Subject: [PATCH 086/442] Perform processing that does not use the database
before connecting to the database (#7168)
---
streaming/index.js | 89 +++++++++++++++++++++++-----------------------
1 file changed, 45 insertions(+), 44 deletions(-)
diff --git a/streaming/index.js b/streaming/index.js
index a42a91242..1b4f8596c 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -329,52 +329,53 @@ const startWorker = (workerId) => {
// Only messages that may require filtering are statuses, since notifications
// are already personalized and deletes do not matter
- if (needsFiltering && event === 'update') {
- pgPool.connect((err, client, done) => {
- if (err) {
- log.error(err);
- return;
- }
-
- const unpackedPayload = payload;
- const targetAccountIds = [unpackedPayload.account.id].concat(unpackedPayload.mentions.map(item => item.id));
- const accountDomain = unpackedPayload.account.acct.split('@')[1];
-
- if (Array.isArray(req.filteredLanguages) && req.filteredLanguages.indexOf(unpackedPayload.language) !== -1) {
- log.silly(req.requestId, `Message ${unpackedPayload.id} filtered by language (${unpackedPayload.language})`);
- done();
- return;
- }
-
- if (req.accountId) {
- const queries = [
- client.query(`SELECT 1 FROM blocks WHERE (account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 2)})) OR (account_id = $2 AND target_account_id = $1) UNION SELECT 1 FROM mutes WHERE account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 2)})`, [req.accountId, unpackedPayload.account.id].concat(targetAccountIds)),
- ];
-
- if (accountDomain) {
- queries.push(client.query('SELECT 1 FROM account_domain_blocks WHERE account_id = $1 AND domain = $2', [req.accountId, accountDomain]));
- }
-
- Promise.all(queries).then(values => {
- done();
-
- if (values[0].rows.length > 0 || (values.length > 1 && values[1].rows.length > 0)) {
- return;
- }
-
- transmit();
- }).catch(err => {
- done();
- log.error(err);
- });
- } else {
- done();
- transmit();
- }
- });
- } else {
+ if (!needsFiltering || event !== 'update') {
transmit();
+ return;
}
+
+ const unpackedPayload = payload;
+ const targetAccountIds = [unpackedPayload.account.id].concat(unpackedPayload.mentions.map(item => item.id));
+ const accountDomain = unpackedPayload.account.acct.split('@')[1];
+
+ if (Array.isArray(req.filteredLanguages) && req.filteredLanguages.indexOf(unpackedPayload.language) !== -1) {
+ log.silly(req.requestId, `Message ${unpackedPayload.id} filtered by language (${unpackedPayload.language})`);
+ return;
+ }
+
+ // When the account is not logged in, it is not necessary to confirm the block or mute
+ if (!req.accountId) {
+ transmit();
+ return;
+ }
+
+ pgPool.connect((err, client, done) => {
+ if (err) {
+ log.error(err);
+ return;
+ }
+
+ const queries = [
+ client.query(`SELECT 1 FROM blocks WHERE (account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 2)})) OR (account_id = $2 AND target_account_id = $1) UNION SELECT 1 FROM mutes WHERE account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 2)})`, [req.accountId, unpackedPayload.account.id].concat(targetAccountIds)),
+ ];
+
+ if (accountDomain) {
+ queries.push(client.query('SELECT 1 FROM account_domain_blocks WHERE account_id = $1 AND domain = $2', [req.accountId, accountDomain]));
+ }
+
+ Promise.all(queries).then(values => {
+ done();
+
+ if (values[0].rows.length > 0 || (values.length > 1 && values[1].rows.length > 0)) {
+ return;
+ }
+
+ transmit();
+ }).catch(err => {
+ done();
+ log.error(err);
+ });
+ });
};
subscribe(`${redisPrefix}${id}`, listener);
From 727917e91eea3582586d3ce710826ef33ae26ffb Mon Sep 17 00:00:00 2001
From: abcang
Date: Tue, 17 Apr 2018 20:50:33 +0900
Subject: [PATCH 087/442] Fix caret position after inserting emoji (#7167)
---
app/javascript/mastodon/actions/compose.js | 3 ++-
.../mastodon/features/compose/components/compose_form.js | 9 +++++++--
.../compose/containers/compose_form_container.js | 4 ++--
app/javascript/mastodon/reducers/compose.js | 7 ++-----
4 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index 59aa6f98d..ea9d9f359 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -446,11 +446,12 @@ export function changeComposeVisibility(value) {
};
};
-export function insertEmojiCompose(position, emoji) {
+export function insertEmojiCompose(position, emoji, needsSpace) {
return {
type: COMPOSE_EMOJI_INSERT,
position,
emoji,
+ needsSpace,
};
};
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.js b/app/javascript/mastodon/features/compose/components/compose_form.js
index fe7bb1cb3..39eb02362 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.js
+++ b/app/javascript/mastodon/features/compose/components/compose_form.js
@@ -19,6 +19,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { length } from 'stringz';
import { countableText } from '../util/counter';
+const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
+
const messages = defineMessages({
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
@@ -144,10 +146,13 @@ export default class ComposeForm extends ImmutablePureComponent {
}
handleEmojiPick = (data) => {
+ const { text } = this.props;
const position = this.autosuggestTextarea.textarea.selectionStart;
const emojiChar = data.native;
- this._restoreCaret = position + emojiChar.length + 1;
- this.props.onPickEmoji(position, data);
+ const needsSpace = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1]);
+
+ this._restoreCaret = position + emojiChar.length + 1 + (needsSpace ? 1 : 0);
+ this.props.onPickEmoji(position, data, needsSpace);
}
render () {
diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js
index ede23d361..c3aa580ee 100644
--- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js
+++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js
@@ -56,8 +56,8 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(uploadCompose(files));
},
- onPickEmoji (position, data) {
- dispatch(insertEmojiCompose(position, data));
+ onPickEmoji (position, data, needsSpace) {
+ dispatch(insertEmojiCompose(position, data, needsSpace));
},
});
diff --git a/app/javascript/mastodon/reducers/compose.js b/app/javascript/mastodon/reducers/compose.js
index 87049ea79..46d9d6c8e 100644
--- a/app/javascript/mastodon/reducers/compose.js
+++ b/app/javascript/mastodon/reducers/compose.js
@@ -36,8 +36,6 @@ import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrde
import uuid from '../uuid';
import { me } from '../initial_state';
-const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
-
const initialState = ImmutableMap({
mounted: 0,
sensitive: false,
@@ -137,9 +135,8 @@ const updateSuggestionTags = (state, token) => {
});
};
-const insertEmoji = (state, position, emojiData) => {
+const insertEmoji = (state, position, emojiData, needsSpace) => {
const oldText = state.get('text');
- const needsSpace = emojiData.custom && position > 0 && !allowedAroundShortCode.includes(oldText[position - 1]);
const emoji = needsSpace ? ' ' + emojiData.native : emojiData.native;
return state.merge({
@@ -288,7 +285,7 @@ export default function compose(state = initialState, action) {
return state;
}
case COMPOSE_EMOJI_INSERT:
- return insertEmoji(state, action.position, action.emoji);
+ return insertEmoji(state, action.position, action.emoji, action.needsSpace);
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
return state
.set('is_submitting', false)
From bb58fc003b5d9ac521a89e7f37c0b7fc1d45a4c9 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 17 Apr 2018 13:50:48 +0200
Subject: [PATCH 088/442] Fix warning about using SQL in order for
Account#partitioned (#7159)
---
app/models/account.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/account.rb b/app/models/account.rb
index 05e817f63..a3436b47c 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -114,7 +114,7 @@ class Account < ApplicationRecord
scope :without_followers, -> { where(followers_count: 0) }
scope :with_followers, -> { where('followers_count > 0') }
scope :expiring, ->(time) { remote.where.not(subscription_expires_at: nil).where('subscription_expires_at < ?', time) }
- scope :partitioned, -> { order('row_number() over (partition by domain)') }
+ scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
scope :silenced, -> { where(silenced: true) }
scope :suspended, -> { where(suspended: true) }
scope :recent, -> { reorder(id: :desc) }
From aab5581c436c306e08df2668c530aab1cf526f20 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 17 Apr 2018 13:51:01 +0200
Subject: [PATCH 089/442] Set Referrer-Policy to origin in web UI and public
pages of private toots (#7162)
Fix #7115
---
app/controllers/home_controller.rb | 5 +++++
app/controllers/statuses_controller.rb | 6 ++++++
2 files changed, 11 insertions(+)
diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb
index b1f8f1ad9..b71424107 100644
--- a/app/controllers/home_controller.rb
+++ b/app/controllers/home_controller.rb
@@ -2,6 +2,7 @@
class HomeController < ApplicationController
before_action :authenticate_user!
+ before_action :set_referrer_policy_header
before_action :set_initial_state_json
def index
@@ -62,4 +63,8 @@ class HomeController < ApplicationController
about_path
end
end
+
+ def set_referrer_policy_header
+ response.headers['Referrer-Policy'] = 'origin'
+ end
end
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index 41f098a43..a2943982a 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -13,6 +13,7 @@ class StatusesController < ApplicationController
before_action :set_link_headers
before_action :check_account_suspension
before_action :redirect_to_original, only: [:show]
+ before_action :set_referrer_policy_header, only: [:show]
before_action :set_cache_headers
def show
@@ -81,4 +82,9 @@ class StatusesController < ApplicationController
def redirect_to_original
redirect_to ::TagManager.instance.url_for(@status.reblog) if @status.reblog?
end
+
+ def set_referrer_policy_header
+ return if @status.public_visibility? || @status.unlisted_visibility?
+ response.headers['Referrer-Policy'] = 'origin'
+ end
end
From 07a7d5959cb722ca77b65b4f7458f861e4b6eb61 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 17 Apr 2018 13:51:14 +0200
Subject: [PATCH 090/442] Fix missing "Administered by" when timeline preview
disabled (#7161)
---
app/views/about/_administration.html.haml | 19 ++++++++++++++
app/views/about/show.html.haml | 30 ++++++-----------------
2 files changed, 27 insertions(+), 22 deletions(-)
create mode 100644 app/views/about/_administration.html.haml
diff --git a/app/views/about/_administration.html.haml b/app/views/about/_administration.html.haml
new file mode 100644
index 000000000..ec5834f9c
--- /dev/null
+++ b/app/views/about/_administration.html.haml
@@ -0,0 +1,19 @@
+.account
+ .account__wrapper
+ - if @instance_presenter.contact_account
+ = link_to TagManager.instance.url_for(@instance_presenter.contact_account), class: 'account__display-name' do
+ .account__avatar-wrapper
+ .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" }
+ %span.display-name
+ %bdi
+ %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account)
+ %span.display-name__account @#{@instance_presenter.contact_account.acct}
+ - else
+ .account__display-name
+ .account__avatar-wrapper
+ .account__avatar{ style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})" }
+ %span.display-name
+ %strong= t 'about.contact_missing'
+ %span.display-name__account= t 'about.contact_unavailable'
+
+ = link_to t('about.learn_more'), about_more_path, class: 'button button-alternative'
diff --git a/app/views/about/show.html.haml b/app/views/about/show.html.haml
index 12213cda2..870dafdf5 100644
--- a/app/views/about/show.html.haml
+++ b/app/views/about/show.html.haml
@@ -110,26 +110,7 @@
%p= t 'about.about_mastodon_html'
%div.contact
%h3= t 'about.administered_by'
-
- .account
- .account__wrapper
- - if @instance_presenter.contact_account
- = link_to TagManager.instance.url_for(@instance_presenter.contact_account), class: 'account__display-name' do
- .account__avatar-wrapper
- .account__avatar{ style: "background-image: url(#{@instance_presenter.contact_account.avatar.url})" }
- %span.display-name
- %bdi
- %strong.display-name__html.emojify= display_name(@instance_presenter.contact_account)
- %span.display-name__account @#{@instance_presenter.contact_account.acct}
- - else
- .account__display-name
- .account__avatar-wrapper
- .account__avatar{ style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})" }
- %span.display-name
- %strong= t 'about.contact_missing'
- %span.display-name__account= t 'about.contact_unavailable'
-
- = link_to t('about.learn_more'), about_more_path, class: 'button button-alternative'
+ = render 'administration'
= render 'features'
@@ -144,8 +125,13 @@
- else
.column-4.non-preview.landing-page__information
.landing-page__features
- %h3= t 'about.what_is_mastodon'
- %p= t 'about.about_mastodon_html'
+ .features-list
+ %div
+ %h3= t 'about.what_is_mastodon'
+ %p= t 'about.about_mastodon_html'
+ %div.contact
+ %h3= t 'about.administered_by'
+ = render 'administration'
= render 'features'
From ef12a2b74c735d78371be3f52b372c03318c3b16 Mon Sep 17 00:00:00 2001
From: Jennifer Kruse
Date: Tue, 17 Apr 2018 06:52:08 -0500
Subject: [PATCH 091/442] Able to deactivate invites if they aren't expired
(#7163)
---
app/views/invites/_invite.html.haml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/invites/_invite.html.haml b/app/views/invites/_invite.html.haml
index 81d67eb7d..1c7ec311d 100644
--- a/app/views/invites/_invite.html.haml
+++ b/app/views/invites/_invite.html.haml
@@ -13,5 +13,5 @@
= l invite.expires_at
%td= table_link_to 'link', public_invite_url(invite_code: invite.code), public_invite_url(invite_code: invite.code)
%td
- - if invite.expired? && policy(invite).destroy?
+ - if !invite.expired? && policy(invite).destroy?
= table_link_to 'times', t('invites.delete'), invite_path(invite), method: :delete
From 204d72fbe49b3749e168ed2cd0ff83706946352a Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Tue, 17 Apr 2018 14:58:11 +0200
Subject: [PATCH 092/442] Feature: add count of account notes to reports
(#7130)
* Reports: Colocate account details with reports
* Reports: Add count of account moderation notes
Sometimes an account will be left with a note instead of the report, this adds a way to quickly see from a given report if this is the case.
---
app/views/admin/accounts/_card.html.haml | 17 ----------------
.../admin/reports/_account_details.html.haml | 20 +++++++++++++++++++
app/views/admin/reports/show.html.haml | 4 ++--
config/locales/en.yml | 10 ++++++++++
4 files changed, 32 insertions(+), 19 deletions(-)
delete mode 100644 app/views/admin/accounts/_card.html.haml
create mode 100644 app/views/admin/reports/_account_details.html.haml
diff --git a/app/views/admin/accounts/_card.html.haml b/app/views/admin/accounts/_card.html.haml
deleted file mode 100644
index 2f5955011..000000000
--- a/app/views/admin/accounts/_card.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-.table-wrapper
- %table.table
- %tbody
- %tr
- %td= t('admin.accounts.show.created_reports')
- %td= link_to pluralize(account.reports.count, t('admin.accounts.show.report')), admin_reports_path(account_id: account.id)
- %tr
- %td= t('admin.accounts.show.targeted_reports')
- %td= link_to pluralize(account.targeted_reports.count, t('admin.accounts.show.report')), admin_reports_path(target_account_id: account.id)
- - if account.silenced? || account.suspended?
- %tr
- %td= t('admin.accounts.moderation.title')
- %td
- - if account.silenced?
- %p= t('admin.accounts.moderation.silenced')
- - if account.suspended?
- %p= t('admin.accounts.moderation.suspended')
diff --git a/app/views/admin/reports/_account_details.html.haml b/app/views/admin/reports/_account_details.html.haml
new file mode 100644
index 000000000..a8af39bef
--- /dev/null
+++ b/app/views/admin/reports/_account_details.html.haml
@@ -0,0 +1,20 @@
+.table-wrapper
+ %table.table
+ %tbody
+ %tr
+ %td= t('admin.reports.account.created_reports')
+ %td= link_to pluralize(account.reports.count, t('admin.reports.account.report')), admin_reports_path(account_id: account.id)
+ %tr
+ %td= t('admin.reports.account.targeted_reports')
+ %td= link_to pluralize(account.targeted_reports.count, t('admin.reports.account.report')), admin_reports_path(target_account_id: account.id)
+ %tr
+ %td= t('admin.reports.account.moderation_notes')
+ %td= link_to pluralize(account.targeted_moderation_notes.count, t('admin.reports.account.note')), admin_reports_path(target_account_id: account.id)
+ - if account.silenced? || account.suspended?
+ %tr
+ %td= t('admin.reports.account.moderation.title')
+ %td
+ - if account.silenced?
+ %p= t('admin.reports.account.moderation.silenced')
+ - if account.suspended?
+ %p= t('admin.reports.account.moderation.suspended')
diff --git a/app/views/admin/reports/show.html.haml b/app/views/admin/reports/show.html.haml
index d57b4adc8..130650001 100644
--- a/app/views/admin/reports/show.html.haml
+++ b/app/views/admin/reports/show.html.haml
@@ -60,11 +60,11 @@
.report-accounts__item
%h3= t('admin.reports.reported_account')
= render 'authorize_follows/card', account: @report.target_account, admin: true
- = render 'admin/accounts/card', account: @report.target_account
+ = render 'admin/reports/account_details', account: @report.target_account
.report-accounts__item
%h3= t('admin.reports.reported_by')
= render 'authorize_follows/card', account: @report.account, admin: true
- = render 'admin/accounts/card', account: @report.account
+ = render 'admin/reports/account_details', account: @report.account
%h3= t('admin.reports.comment.label')
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 4816cc599..20bfd0f8c 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -259,6 +259,16 @@ en:
created_msg: Report note successfully created!
destroyed_msg: Report note successfully deleted!
reports:
+ account:
+ created_reports: Reports created by this account
+ moderation:
+ silenced: Silenced
+ suspended: Suspended
+ title: Moderation
+ moderation_notes: Moderation Notes
+ note: note
+ report: report
+ targeted_reports: Reports made about this account
action_taken_by: Action taken by
are_you_sure: Are you sure?
assign_to_self: Assign to me
From 897199910fc29d17b4a019b6ee2473e138d777a2 Mon Sep 17 00:00:00 2001
From: abcang
Date: Tue, 17 Apr 2018 22:23:46 +0900
Subject: [PATCH 093/442] Improve web api protect (#6343)
---
app/controllers/api/web/base_controller.rb | 9 +++++++++
app/controllers/api/web/embeds_controller.rb | 2 +-
.../api/web/push_subscriptions_controller.rb | 3 +--
app/controllers/api/web/settings_controller.rb | 2 +-
.../mastodon/actions/push_notifications/registerer.js | 10 +++++-----
app/javascript/mastodon/actions/settings.js | 2 +-
6 files changed, 18 insertions(+), 10 deletions(-)
create mode 100644 app/controllers/api/web/base_controller.rb
diff --git a/app/controllers/api/web/base_controller.rb b/app/controllers/api/web/base_controller.rb
new file mode 100644
index 000000000..8da549b3a
--- /dev/null
+++ b/app/controllers/api/web/base_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Api::Web::BaseController < Api::BaseController
+ protect_from_forgery with: :exception
+
+ rescue_from ActionController::InvalidAuthenticityToken do
+ render json: { error: "Can't verify CSRF token authenticity." }, status: 422
+ end
+end
diff --git a/app/controllers/api/web/embeds_controller.rb b/app/controllers/api/web/embeds_controller.rb
index 2ed516161..f2fe74b17 100644
--- a/app/controllers/api/web/embeds_controller.rb
+++ b/app/controllers/api/web/embeds_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Api::Web::EmbedsController < Api::BaseController
+class Api::Web::EmbedsController < Api::Web::BaseController
respond_to :json
before_action :require_user!
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb
index c611031ab..249e7c186 100644
--- a/app/controllers/api/web/push_subscriptions_controller.rb
+++ b/app/controllers/api/web/push_subscriptions_controller.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-class Api::Web::PushSubscriptionsController < Api::BaseController
+class Api::Web::PushSubscriptionsController < Api::Web::BaseController
respond_to :json
before_action :require_user!
- protect_from_forgery with: :exception
def create
active_session = current_session
diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb
index f6739d506..e3178bf48 100644
--- a/app/controllers/api/web/settings_controller.rb
+++ b/app/controllers/api/web/settings_controller.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class Api::Web::SettingsController < Api::BaseController
+class Api::Web::SettingsController < Api::Web::BaseController
respond_to :json
before_action :require_user!
diff --git a/app/javascript/mastodon/actions/push_notifications/registerer.js b/app/javascript/mastodon/actions/push_notifications/registerer.js
index f17d929a6..60b215f02 100644
--- a/app/javascript/mastodon/actions/push_notifications/registerer.js
+++ b/app/javascript/mastodon/actions/push_notifications/registerer.js
@@ -36,7 +36,7 @@ const subscribe = (registration) =>
const unsubscribe = ({ registration, subscription }) =>
subscription ? subscription.unsubscribe().then(() => registration) : registration;
-const sendSubscriptionToBackend = (getState, subscription) => {
+const sendSubscriptionToBackend = (subscription) => {
const params = { subscription };
if (me) {
@@ -46,7 +46,7 @@ const sendSubscriptionToBackend = (getState, subscription) => {
}
}
- return api(getState).post('/api/web/push_subscriptions', params).then(response => response.data);
+ return api().post('/api/web/push_subscriptions', params).then(response => response.data);
};
// Last one checks for payload support: https://web-push-book.gauntface.com/chapter-06/01-non-standards-browsers/#no-payload
@@ -85,13 +85,13 @@ export function register () {
} else {
// Something went wrong, try to subscribe again
return unsubscribe({ registration, subscription }).then(subscribe).then(
- subscription => sendSubscriptionToBackend(getState, subscription));
+ subscription => sendSubscriptionToBackend(subscription));
}
}
// No subscription, try to subscribe
return subscribe(registration).then(
- subscription => sendSubscriptionToBackend(getState, subscription));
+ subscription => sendSubscriptionToBackend(subscription));
})
.then(subscription => {
// If we got a PushSubscription (and not a subscription object from the backend)
@@ -134,7 +134,7 @@ export function saveSettings() {
const alerts = state.get('alerts');
const data = { alerts };
- api(getState).put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
+ api().put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
data,
}).then(() => {
if (me) {
diff --git a/app/javascript/mastodon/actions/settings.js b/app/javascript/mastodon/actions/settings.js
index 5634a11ef..6bf85e464 100644
--- a/app/javascript/mastodon/actions/settings.js
+++ b/app/javascript/mastodon/actions/settings.js
@@ -24,7 +24,7 @@ const debouncedSave = debounce((dispatch, getState) => {
const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS();
- api(getState).put('/api/web/settings', { data })
+ api().put('/api/web/settings', { data })
.then(() => dispatch({ type: SETTING_SAVE }))
.catch(error => dispatch(showAlertForError(error)));
}, 5000, { trailing: true });
From 11715454d033784bf6176b75a954e5c28b5d79e5 Mon Sep 17 00:00:00 2001
From: Sam Schlinkert
Date: Tue, 17 Apr 2018 17:25:54 -0400
Subject: [PATCH 094/442] Make scroll bars wider (#7060)
* Set scrollbars to 12 px wide rather than 8px
Should overwrite the setting in reset.scss. This is untested at this point.
* removes scrollbar height and width specifications from reset.scss and basics.scss
---
app/javascript/styles/mastodon/reset.scss | 5 -----
1 file changed, 5 deletions(-)
diff --git a/app/javascript/styles/mastodon/reset.scss b/app/javascript/styles/mastodon/reset.scss
index cc5ba9d7c..58d4de35f 100644
--- a/app/javascript/styles/mastodon/reset.scss
+++ b/app/javascript/styles/mastodon/reset.scss
@@ -53,11 +53,6 @@ table {
border-spacing: 0;
}
-::-webkit-scrollbar {
- width: 8px;
- height: 8px;
-}
-
::-webkit-scrollbar-thumb {
background: lighten($ui-base-color, 4%);
border: 0px none $base-border-color;
From e5dd385431d8a3c35ceb3fd9d76fb0549c720f35 Mon Sep 17 00:00:00 2001
From: ThibG
Date: Tue, 17 Apr 2018 23:35:45 +0200
Subject: [PATCH 095/442] Allow boosting own private toots (#6157)
* Adjust policy to allow boosting own private toots
* Add ability to reblog private toots from dropdown menu
---
app/javascript/mastodon/components/status_action_bar.js | 4 ++++
.../mastodon/features/status/components/action_bar.js | 4 ++++
app/policies/status_policy.rb | 2 +-
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/app/javascript/mastodon/components/status_action_bar.js b/app/javascript/mastodon/components/status_action_bar.js
index 10f34b0c7..e58625582 100644
--- a/app/javascript/mastodon/components/status_action_bar.js
+++ b/app/javascript/mastodon/components/status_action_bar.js
@@ -18,6 +18,8 @@ const messages = defineMessages({
more: { id: 'status.more', defaultMessage: 'More' },
replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' },
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
+ reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost to original audience' },
+ cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
open: { id: 'status.open', defaultMessage: 'Expand this status' },
@@ -150,6 +152,8 @@ export default class StatusActionBar extends ImmutablePureComponent {
if (status.getIn(['account', 'id']) === me) {
if (publicStatus) {
menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
+ } else {
+ menu.push({ text: intl.formatMessage(status.get('reblog') ? messages.reblog_private : messages.cancel_reblog_private), action: this.handleReblogClick });
}
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js
index 4aa6b08f2..fc34c8cdc 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.js
+++ b/app/javascript/mastodon/features/status/components/action_bar.js
@@ -12,6 +12,8 @@ const messages = defineMessages({
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
reply: { id: 'status.reply', defaultMessage: 'Reply' },
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
+ reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost to original audience' },
+ cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' },
mute: { id: 'status.mute', defaultMessage: 'Mute @{name}' },
@@ -120,6 +122,8 @@ export default class ActionBar extends React.PureComponent {
if (me === status.getIn(['account', 'id'])) {
if (publicStatus) {
menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
+ } else {
+ menu.push({ text: intl.formatMessage(status.get('reblog') ? messages.reblog_private : messages.cancel_reblog_private), action: this.handleReblogClick });
}
menu.push(null);
diff --git a/app/policies/status_policy.rb b/app/policies/status_policy.rb
index 0373fdf04..5573289b6 100644
--- a/app/policies/status_policy.rb
+++ b/app/policies/status_policy.rb
@@ -16,7 +16,7 @@ class StatusPolicy < ApplicationPolicy
end
def reblog?
- !direct? && !private? && show?
+ !direct? && (!private? || owned?) && show?
end
def destroy?
From fad7b9f5f297f970056d86cef0139e709ed47516 Mon Sep 17 00:00:00 2001
From: Neil Moore
Date: Tue, 17 Apr 2018 21:33:59 -0400
Subject: [PATCH 096/442] Adds keyboard hotkey for revealing/hiding statuses
(#7173)
Resolves #5550
---
app/javascript/mastodon/components/status.js | 5 +++++
app/javascript/mastodon/features/status/index.js | 5 +++++
app/javascript/mastodon/features/ui/index.js | 1 +
3 files changed, 11 insertions(+)
diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js
index 6129b3f1e..e5f7c9399 100644
--- a/app/javascript/mastodon/components/status.js
+++ b/app/javascript/mastodon/components/status.js
@@ -122,6 +122,10 @@ export default class Status extends ImmutablePureComponent {
this.props.onMoveDown(this.props.status.get('id'));
}
+ handleHotkeyToggleHidden = () => {
+ this.props.onToggleHidden(this._properStatus());
+ }
+
_properStatus () {
const { status } = this.props;
@@ -224,6 +228,7 @@ export default class Status extends ImmutablePureComponent {
openProfile: this.handleHotkeyOpenProfile,
moveUp: this.handleHotkeyMoveUp,
moveDown: this.handleHotkeyMoveDown,
+ toggleHidden: this.handleHotkeyToggleHidden,
};
return (
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index 55eff0823..d5af2a459 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -244,6 +244,10 @@ export default class Status extends ImmutablePureComponent {
this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
}
+ handleHotkeyToggleHidden = () => {
+ this.handleToggleHidden(this.props.status);
+ }
+
handleMoveUp = id => {
const { status, ancestorsIds, descendantsIds } = this.props;
@@ -354,6 +358,7 @@ export default class Status extends ImmutablePureComponent {
boost: this.handleHotkeyBoost,
mention: this.handleHotkeyMention,
openProfile: this.handleHotkeyOpenProfile,
+ toggleHidden: this.handleHotkeyToggleHidden,
};
return (
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 8b905fa1d..d2ef19e47 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -85,6 +85,7 @@ const keyMap = {
goToProfile: 'g u',
goToBlocked: 'g b',
goToMuted: 'g m',
+ toggleHidden: 'x',
};
class SwitchingColumnsArea extends React.PureComponent {
From aedfea3554dc5cd60f4bebd828109d1ef4327814 Mon Sep 17 00:00:00 2001
From: luzi82
Date: Wed, 18 Apr 2018 13:28:26 +0800
Subject: [PATCH 097/442] zh-HK translation (#7177)
* zh-HK translation
* zh-HK fix
* zh-HK translation
* add missing zh-HK translate
* fix translate
* i18n-tasks normalize
---
app/javascript/mastodon/locales/zh-HK.json | 10 ++--
config/locales/devise.zh-HK.yml | 4 +-
config/locales/doorkeeper.zh-HK.yml | 4 +-
config/locales/simple_form.zh-HK.yml | 6 +++
config/locales/zh-HK.yml | 63 ++++++++++++++++++++--
5 files changed, 75 insertions(+), 12 deletions(-)
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index bebb33e57..28685f4d8 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -74,7 +74,7 @@
"confirmations.block.confirm": "封鎖",
"confirmations.block.message": "你確定要封鎖{name}嗎?",
"confirmations.delete.confirm": "刪除",
- "confirmations.delete.message": "你確定要刪除{name}嗎?",
+ "confirmations.delete.message": "你確定要刪除這文章嗎?",
"confirmations.delete_list.confirm": "刪除",
"confirmations.delete_list.message": "你確定要永久刪除這列表嗎?",
"confirmations.domain_block.confirm": "隱藏整個網站",
@@ -99,11 +99,11 @@
"emoji_button.search_results": "搜尋結果",
"emoji_button.symbols": "符號",
"emoji_button.travel": "旅遊景物",
- "empty_column.community": "本站時間軸暫時未有內容,快文章來搶頭香啊!",
+ "empty_column.community": "本站時間軸暫時未有內容,快寫一點東西來搶頭香啊!",
"empty_column.hashtag": "這個標籤暫時未有內容。",
"empty_column.home": "你還沒有關注任何用戶。快看看{public},向其他用戶搭訕吧。",
"empty_column.home.public_timeline": "公共時間軸",
- "empty_column.list": "There is nothing in this list yet.",
+ "empty_column.list": "這個列表暫時未有內容。",
"empty_column.notifications": "你沒有任何通知紀錄,快向其他用戶搭訕吧。",
"empty_column.public": "跨站時間軸暫時沒有內容!快寫一些公共的文章,或者關注另一些服務站的用戶吧!你和本站、友站的交流,將決定這裏出現的內容。",
"follow_request.authorize": "批准",
@@ -240,7 +240,7 @@
"status.block": "封鎖 @{name}",
"status.cannot_reblog": "這篇文章無法被轉推",
"status.delete": "刪除",
- "status.direct": "Direct message @{name}",
+ "status.direct": "私訊 @{name}",
"status.embed": "鑲嵌",
"status.favourite": "收藏",
"status.load_more": "載入更多",
@@ -270,7 +270,7 @@
"tabs_bar.home": "主頁",
"tabs_bar.local_timeline": "本站",
"tabs_bar.notifications": "通知",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "搜尋",
"ui.beforeunload": "如果你現在離開 Mastodon,你的草稿內容將會被丟棄。",
"upload_area.title": "將檔案拖放至此上載",
"upload_button.label": "上載媒體檔案",
diff --git a/config/locales/devise.zh-HK.yml b/config/locales/devise.zh-HK.yml
index 12d6e3c2c..ca16e06aa 100644
--- a/config/locales/devise.zh-HK.yml
+++ b/config/locales/devise.zh-HK.yml
@@ -78,5 +78,5 @@ zh-HK:
not_found: 找不到
not_locked: 並未被鎖定
not_saved:
- one: 1 個錯誤令 %{resource} 被法被儲存︰
- other: "%{count} 個錯誤令 %{resource} 被法被儲存︰"
+ one: 1 個錯誤令 %{resource} 無法被儲存︰
+ other: "%{count} 個錯誤令 %{resource} 無法被儲存︰"
diff --git a/config/locales/doorkeeper.zh-HK.yml b/config/locales/doorkeeper.zh-HK.yml
index 747108762..4f46a416a 100644
--- a/config/locales/doorkeeper.zh-HK.yml
+++ b/config/locales/doorkeeper.zh-HK.yml
@@ -14,7 +14,7 @@ zh-HK:
redirect_uri:
fragment_present: URI 不可包含 "#fragment" 部份
invalid_uri: 必需有正確的 URI.
- relative_uri: 必需為絕對 URI.
+ relative_uri: 必需為完整 URI.
secured_uri: 必需使用有 HTTPS/SSL 加密的 URI.
doorkeeper:
applications:
@@ -63,7 +63,7 @@ zh-HK:
prompt: 應用程式 %{client_name} 要求得到你用戶的部份權限
title: 需要用戶授權
show:
- title: Copy this authorization code and paste it to the application.
+ title: 請把這個授權碼複製到應用程式中。
authorized_applications:
buttons:
revoke: 取消授權
diff --git a/config/locales/simple_form.zh-HK.yml b/config/locales/simple_form.zh-HK.yml
index da0292a90..6b890b036 100644
--- a/config/locales/simple_form.zh-HK.yml
+++ b/config/locales/simple_form.zh-HK.yml
@@ -6,6 +6,7 @@ zh-HK:
avatar: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 2MB,會縮裁成 400x400px
digest: 僅在你長時間未登錄,且收到了私信時發送
display_name: 最多 30 個字元
+ fields: 個人資料頁可顯示多至 4 個項目
header: 支援 PNG, GIF 或 JPG 圖片,檔案最大為 2MB,會縮裁成 700x335px
locked: 你必須人手核准每個用戶對你的關注請求,而你的文章私隱會被預設為「只有關注你的人能看」
note: 最多 160 個字元
@@ -18,6 +19,10 @@ zh-HK:
user:
filtered_languages: 下面被選擇的語言的文章將不會出現在你的公共時間軸上。
labels:
+ account:
+ fields:
+ name: 標籤
+ value: 內容
defaults:
avatar: 個人頭像
confirm_new_password: 確認新密碼
@@ -27,6 +32,7 @@ zh-HK:
display_name: 顯示名稱
email: 電郵地址
expires_in: 失效時間
+ fields: 資料
filtered_languages: 封鎖下面語言的文章
header: 個人頁面頂部
locale: 語言
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index 5c1feabfc..964ff5811 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -4,6 +4,7 @@ zh-HK:
about_hashtag_html: 這些是包含「#%{hashtag}」標籤的公開文章。只要你有任何 Mastodon 服務站、或者聯盟網站的用戶,便可以與他們互動。
about_mastodon_html: Mastodon(萬象)是自由、開源的社交網絡。服務站各自獨立而互連,避免單一商業機構壟斷。找你所信任的服務站,建立帳號,你即可與任何服務站上的用戶溝通,享受無縫的網絡交流。
about_this: 關於本服務站
+ administered_by: 管理者:
closed_registrations: 本服務站暫時停止接受登記。
contact: 聯絡
contact_missing: 未設定
@@ -60,7 +61,15 @@ zh-HK:
destroyed_msg: 管理記錄已被刪除
accounts:
are_you_sure: 你確定嗎?
+ avatar: 頭像
by_domain: 域名
+ change_email:
+ changed_msg: 帳號電郵更新成功!
+ current_email: 現時電郵
+ label: 改變電郵
+ new_email: 新的電郵
+ submit: 改變電郵
+ title: 改變 %{username} 的電郵
confirm: 確定
confirmed: 已確定
demote: 降任
@@ -108,6 +117,7 @@ zh-HK:
public: 公共
push_subscription_expires: PuSH 訂閱過期
redownload: 更新頭像
+ remove_avatar: 取消頭像
reset: 重設
reset_password: 重設密碼
resubscribe: 重新訂閱
@@ -128,6 +138,7 @@ zh-HK:
statuses: 文章
subscribe: 訂閱
title: 用戶
+ unconfirmed_email: 未確認的電郵
undo_silenced: 解除靜音
undo_suspension: 解除停權
unsubscribe: 取消訂閱
@@ -135,6 +146,8 @@ zh-HK:
web: 用戶頁面
action_logs:
actions:
+ assigned_to_self_report: "%{name} 指派了 %{target} 的舉報給自己"
+ change_email_user: "%{name} 改變了用戶 %{target} 的電郵地址"
confirm_user: "%{name} 確認了用戶 %{target} 的電郵地址"
create_custom_emoji: "%{name} 加入自訂表情符號 %{target}"
create_domain_block: "%{name} 阻隔了網域 %{target}"
@@ -150,10 +163,13 @@ zh-HK:
enable_user: "%{name} 把用戶 %{target} 設定為允許登入"
memorialize_account: "%{name} 把 %{target} 設定為追悼帳戶"
promote_user: "%{name} 對用戶 %{target} 进行了升任操作"
+ remove_avatar_user: "%{name} 取消了 %{target} 的頭像"
+ reopen_report: "%{name} 重開 %{target} 的舉報"
reset_password_user: "%{name} 重設了用戶 %{target} 的密碼"
resolve_report: "%{name} 處理了 %{target} 的舉報"
silence_account: "%{name} 靜音了用戶 %{target}"
suspend_account: "%{name} 停權了用戶 %{target}"
+ unassigned_report: "%{name} 取消指派 %{target} 的舉報"
unsilence_account: "%{name} 取消了用戶 %{target} 的靜音狀態"
unsuspend_account: "%{name} 取消了用戶 %{target} 的停權狀態"
update_custom_emoji: "%{name} 更新了自訂表情符號 %{target}"
@@ -238,29 +254,60 @@ zh-HK:
expired: 已失效
title: 篩選
title: 邀請用戶
+ report_notes:
+ created_msg: 舉報筆記已建立。
+ destroyed_msg: 舉報筆記已刪除。
reports:
+ account:
+ created_reports: 由此帳號發出的舉報
+ moderation:
+ silenced: 被靜音的
+ suspended: 被停權的
+ title: 管理操作
+ moderation_notes: 管理筆記
+ note: 筆記
+ report: 舉報
+ targeted_reports: 關於此帳號的舉報
action_taken_by: 操作執行者
are_you_sure: 你確認嗎?
+ assign_to_self: 指派給自己
+ assigned: 指派負責人
comment:
label: 詳細解釋
none: 沒有
+ created_at: 日期
delete: 刪除
+ history: 執行紀錄
id: ID
mark_as_resolved: 標示為「已處理」
+ mark_as_unresolved: 標示為「未處理」
+ notes:
+ create: 建立筆記
+ create_and_resolve: 建立筆記並標示為「已處理」
+ create_and_unresolve: 建立筆記並標示為「未處理」
+ delete: 刪除
+ label: 管理筆記
+ new_label: 建立管理筆記
+ placeholder: 記錄已執行的動作,或其他更新
nsfw:
'false': 取消 NSFW 標記
'true': 添加 NSFW 標記
+ reopen: 重開舉報
report: '舉報 #%{id}'
report_contents: 舉報內容
reported_account: 舉報用戶
reported_by: 舉報者
resolved: 已處理
+ resolved_msg: 舉報已處理。
silence_account: 將用戶靜音
status: 狀態
+ statuses: 被舉報的文章
suspend_account: 將用戶停權
target: 對象
title: 舉報
+ unassign: 取消指派
unresolved: 未處理
+ updated_at: 更新
view: 檢視
settings:
activity_api_enabled:
@@ -381,6 +428,7 @@ zh-HK:
security: 登入資訊
set_new_password: 設定新密碼
authorize_follow:
+ already_following: 你已經關注了這個帳號
error: 對不起,尋找這個跨站用戶的過程發生錯誤
follow: 關注
follow_request: 關注請求已發送给:
@@ -473,6 +521,7 @@ zh-HK:
'21600': 6 小時後
'3600': 1 小時後
'43200': 12 小時後
+ '604800': 1 週後
'86400': 1 天後
expires_in_prompt: 永不過期
generate: 生成邀請連結
@@ -574,6 +623,10 @@ zh-HK:
missing_resource: 無法找到你用戶的轉接網址
proceed: 下一步
prompt: 你希望關注︰
+ remote_unfollow:
+ error: 錯誤
+ title: 標題
+ unfollowed: 取消關注
sessions:
activity: 最近活動
browser: 瀏覽器
@@ -593,7 +646,7 @@ zh-HK:
safari: Safari
uc_browser: UC瀏覽器
weibo: 新浪微博
- current_session: 目前的 session
+ current_session: 目前的作業階段
description: "%{platform} 上的 %{browser}"
explanation: 這些是現在正登入於你的 Mastodon 帳號的瀏覽器。
ip: IP 位址
@@ -611,8 +664,8 @@ zh-HK:
windows_mobile: Windows Mobile
windows_phone: Windows Phone
revoke: 取消
- revoke_success: Session 取消成功。
- title: Session
+ revoke_success: 作業階段取消成功。
+ title: 作業階段
settings:
authorized_apps: 授權應用程式
back: 回到 Mastodon
@@ -677,6 +730,10 @@ zh-HK:
setup: 設定
wrong_code: 你輸入的認證碼並不正確!可能伺服器時間和你手機不一致,請檢查你手機的時鐘,或與本站管理員聯絡。
user_mailer:
+ backup_ready:
+ explanation: 你要求的 Mastodon 帳號完整備份檔案現已就緒,可供下載。
+ subject: 你的備份檔已可供下載
+ title: 檔案匯出
welcome:
edit_profile_action: 設定個人資料
edit_profile_step: 你可以設定你的個人資料,包括上傳頭像、橫幅圖片、更改顯示名稱等等。如果你想在新的關注者關注你之前對他們進行審核,你也可以選擇為你的帳戶設為「私人」。
From 156b916caf4ec902a8db525843e95c1a42350207 Mon Sep 17 00:00:00 2001
From: Kaito Sinclaire
Date: Wed, 18 Apr 2018 04:09:06 -0700
Subject: [PATCH 098/442] Direct messages column (#4514)
* Added a timeline for Direct statuses
* Lists all Direct statuses you've sent and received
* Displayed in Getting Started
* Streaming server support for direct TL
* Changes to match other timelines in 2.0
---
.../api/v1/timelines/direct_controller.rb | 60 ++++++++++
app/javascript/mastodon/actions/compose.js | 2 +
app/javascript/mastodon/actions/streaming.js | 1 +
app/javascript/mastodon/actions/timelines.js | 1 +
.../containers/column_settings_container.js | 17 +++
.../features/direct_timeline/index.js | 104 ++++++++++++++++++
.../features/getting_started/index.js | 15 ++-
.../features/ui/components/columns_area.js | 3 +-
app/javascript/mastodon/features/ui/index.js | 8 ++
.../features/ui/util/async-components.js | 4 +
app/javascript/mastodon/locales/ar.json | 5 +
app/javascript/mastodon/locales/bg.json | 5 +
app/javascript/mastodon/locales/ca.json | 5 +
app/javascript/mastodon/locales/de.json | 5 +
.../mastodon/locales/defaultMessages.json | 33 ++++++
app/javascript/mastodon/locales/en.json | 5 +
app/javascript/mastodon/locales/eo.json | 5 +
app/javascript/mastodon/locales/es.json | 5 +
app/javascript/mastodon/locales/fa.json | 5 +
app/javascript/mastodon/locales/fi.json | 5 +
app/javascript/mastodon/locales/fr.json | 5 +
app/javascript/mastodon/locales/gl.json | 5 +
app/javascript/mastodon/locales/he.json | 5 +
app/javascript/mastodon/locales/hr.json | 5 +
app/javascript/mastodon/locales/hu.json | 5 +
app/javascript/mastodon/locales/hy.json | 5 +
app/javascript/mastodon/locales/id.json | 5 +
app/javascript/mastodon/locales/io.json | 5 +
app/javascript/mastodon/locales/it.json | 5 +
app/javascript/mastodon/locales/ja.json | 5 +
app/javascript/mastodon/locales/ko.json | 5 +
app/javascript/mastodon/locales/nl.json | 5 +
app/javascript/mastodon/locales/no.json | 5 +
app/javascript/mastodon/locales/oc.json | 5 +
app/javascript/mastodon/locales/pl.json | 5 +
app/javascript/mastodon/locales/pt-BR.json | 5 +
app/javascript/mastodon/locales/pt.json | 5 +
app/javascript/mastodon/locales/ru.json | 5 +
app/javascript/mastodon/locales/sk.json | 5 +
app/javascript/mastodon/locales/sr-Latn.json | 5 +
app/javascript/mastodon/locales/sr.json | 5 +
app/javascript/mastodon/locales/sv.json | 5 +
app/javascript/mastodon/locales/th.json | 5 +
app/javascript/mastodon/locales/tr.json | 5 +
app/javascript/mastodon/locales/uk.json | 5 +
app/javascript/mastodon/locales/zh-CN.json | 5 +
app/javascript/mastodon/locales/zh-HK.json | 5 +
app/javascript/mastodon/locales/zh-TW.json | 5 +
app/javascript/mastodon/reducers/contexts.js | 5 +-
app/javascript/mastodon/reducers/settings.js | 6 +
app/models/status.rb | 8 ++
app/services/batched_remove_status_service.rb | 11 ++
app/services/fan_out_on_write_service.rb | 13 ++-
app/services/remove_status_service.rb | 8 ++
config/routes.rb | 1 +
spec/models/status_spec.rb | 49 +++++++++
streaming/index.js | 7 ++
yarn.lock | 12 +-
58 files changed, 538 insertions(+), 15 deletions(-)
create mode 100644 app/controllers/api/v1/timelines/direct_controller.rb
create mode 100644 app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js
create mode 100644 app/javascript/mastodon/features/direct_timeline/index.js
diff --git a/app/controllers/api/v1/timelines/direct_controller.rb b/app/controllers/api/v1/timelines/direct_controller.rb
new file mode 100644
index 000000000..d455227eb
--- /dev/null
+++ b/app/controllers/api/v1/timelines/direct_controller.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+class Api::V1::Timelines::DirectController < Api::BaseController
+ before_action -> { doorkeeper_authorize! :read }, only: [:show]
+ before_action :require_user!, only: [:show]
+ after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
+
+ respond_to :json
+
+ def show
+ @statuses = load_statuses
+ render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
+ end
+
+ private
+
+ def load_statuses
+ cached_direct_statuses
+ end
+
+ def cached_direct_statuses
+ cache_collection direct_statuses, Status
+ end
+
+ def direct_statuses
+ direct_timeline_statuses.paginate_by_max_id(
+ limit_param(DEFAULT_STATUSES_LIMIT),
+ params[:max_id],
+ params[:since_id]
+ )
+ end
+
+ def direct_timeline_statuses
+ Status.as_direct_timeline(current_account)
+ end
+
+ def insert_pagination_headers
+ set_pagination_headers(next_path, prev_path)
+ end
+
+ def pagination_params(core_params)
+ params.permit(:local, :limit).merge(core_params)
+ end
+
+ def next_path
+ api_v1_timelines_direct_url pagination_params(max_id: pagination_max_id)
+ end
+
+ def prev_path
+ api_v1_timelines_direct_url pagination_params(since_id: pagination_since_id)
+ end
+
+ def pagination_max_id
+ @statuses.last.id
+ end
+
+ def pagination_since_id
+ @statuses.first.id
+ end
+end
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index ea9d9f359..eee9c6928 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -145,6 +145,8 @@ export function submitCompose() {
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
insertIfOnline('community');
insertIfOnline('public');
+ } else if (response.data.visibility === 'direct') {
+ insertIfOnline('direct');
}
}).catch(function (error) {
dispatch(submitComposeFail(error));
diff --git a/app/javascript/mastodon/actions/streaming.js b/app/javascript/mastodon/actions/streaming.js
index f76510cdb..14215ab6d 100644
--- a/app/javascript/mastodon/actions/streaming.js
+++ b/app/javascript/mastodon/actions/streaming.js
@@ -46,4 +46,5 @@ export const connectCommunityStream = () => connectTimelineStream('community', '
export const connectMediaStream = () => connectTimelineStream('community', 'public:local');
export const connectPublicStream = () => connectTimelineStream('public', 'public');
export const connectHashtagStream = (tag) => connectTimelineStream(`hashtag:${tag}`, `hashtag&tag=${tag}`);
+export const connectDirectStream = () => connectTimelineStream('direct', 'direct');
export const connectListStream = (id) => connectTimelineStream(`list:${id}`, `list&list=${id}`);
diff --git a/app/javascript/mastodon/actions/timelines.js b/app/javascript/mastodon/actions/timelines.js
index 5be07126d..eca847ee7 100644
--- a/app/javascript/mastodon/actions/timelines.js
+++ b/app/javascript/mastodon/actions/timelines.js
@@ -87,6 +87,7 @@ export function expandTimeline(timelineId, path, params = {}) {
export const expandHomeTimeline = ({ maxId } = {}) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId });
export const expandPublicTimeline = ({ maxId } = {}) => expandTimeline('public', '/api/v1/timelines/public', { max_id: maxId });
export const expandCommunityTimeline = ({ maxId } = {}) => expandTimeline('community', '/api/v1/timelines/public', { local: true, max_id: maxId });
+export const expandDirectTimeline = ({ maxId } = {}) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId });
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true });
diff --git a/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js b/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js
new file mode 100644
index 000000000..1833f69e5
--- /dev/null
+++ b/app/javascript/mastodon/features/direct_timeline/containers/column_settings_container.js
@@ -0,0 +1,17 @@
+import { connect } from 'react-redux';
+import ColumnSettings from '../../community_timeline/components/column_settings';
+import { changeSetting } from '../../../actions/settings';
+
+const mapStateToProps = state => ({
+ settings: state.getIn(['settings', 'direct']),
+});
+
+const mapDispatchToProps = dispatch => ({
+
+ onChange (key, checked) {
+ dispatch(changeSetting(['direct', ...key], checked));
+ },
+
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);
diff --git a/app/javascript/mastodon/features/direct_timeline/index.js b/app/javascript/mastodon/features/direct_timeline/index.js
new file mode 100644
index 000000000..fda57f69a
--- /dev/null
+++ b/app/javascript/mastodon/features/direct_timeline/index.js
@@ -0,0 +1,104 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import PropTypes from 'prop-types';
+import StatusListContainer from '../ui/containers/status_list_container';
+import Column from '../../components/column';
+import ColumnHeader from '../../components/column_header';
+import { expandDirectTimeline } from '../../actions/timelines';
+import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
+import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
+import ColumnSettingsContainer from './containers/column_settings_container';
+import { connectDirectStream } from '../../actions/streaming';
+
+const messages = defineMessages({
+ title: { id: 'column.direct', defaultMessage: 'Direct messages' },
+});
+
+const mapStateToProps = state => ({
+ hasUnread: state.getIn(['timelines', 'direct', 'unread']) > 0,
+});
+
+@connect(mapStateToProps)
+@injectIntl
+export default class DirectTimeline extends React.PureComponent {
+
+ static propTypes = {
+ dispatch: PropTypes.func.isRequired,
+ columnId: PropTypes.string,
+ intl: PropTypes.object.isRequired,
+ hasUnread: PropTypes.bool,
+ multiColumn: PropTypes.bool,
+ };
+
+ handlePin = () => {
+ const { columnId, dispatch } = this.props;
+
+ if (columnId) {
+ dispatch(removeColumn(columnId));
+ } else {
+ dispatch(addColumn('DIRECT', {}));
+ }
+ }
+
+ handleMove = (dir) => {
+ const { columnId, dispatch } = this.props;
+ dispatch(moveColumn(columnId, dir));
+ }
+
+ handleHeaderClick = () => {
+ this.column.scrollTop();
+ }
+
+ componentDidMount () {
+ const { dispatch } = this.props;
+
+ dispatch(expandDirectTimeline());
+ this.disconnect = dispatch(connectDirectStream());
+ }
+
+ componentWillUnmount () {
+ if (this.disconnect) {
+ this.disconnect();
+ this.disconnect = null;
+ }
+ }
+
+ setRef = c => {
+ this.column = c;
+ }
+
+ handleLoadMore = maxId => {
+ this.props.dispatch(expandDirectTimeline({ maxId }));
+ }
+
+ render () {
+ const { intl, hasUnread, columnId, multiColumn } = this.props;
+ const pinned = !!columnId;
+
+ return (
+
+
+
+
+
+ }
+ />
+
+ );
+ }
+
+}
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index 053a1ca17..4a249f301 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -19,6 +19,7 @@ const messages = defineMessages({
navigation_subheading: { id: 'column_subheading.navigation', defaultMessage: 'Navigation' },
settings_subheading: { id: 'column_subheading.settings', defaultMessage: 'Settings' },
community_timeline: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
+ direct: { id: 'navigation_bar.direct', defaultMessage: 'Direct messages' },
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
sign_out: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
@@ -98,20 +99,24 @@ export default class GettingStarted extends ImmutablePureComponent {
}
}
+ if (!multiColumn || !columns.find(item => item.get('id') === 'DIRECT')) {
+ navItems.push();
+ }
+
navItems.push(
- ,
-
+ ,
+
);
if (myAccount.get('locked')) {
- navItems.push();
+ navItems.push();
}
if (multiColumn) {
- navItems.push();
+ navItems.push();
}
- navItems.push();
+ navItems.push();
return (
diff --git a/app/javascript/mastodon/features/ui/components/columns_area.js b/app/javascript/mastodon/features/ui/components/columns_area.js
index 05cdb4e3b..0a62cbbeb 100644
--- a/app/javascript/mastodon/features/ui/components/columns_area.js
+++ b/app/javascript/mastodon/features/ui/components/columns_area.js
@@ -12,7 +12,7 @@ import BundleContainer from '../containers/bundle_container';
import ColumnLoading from './column_loading';
import DrawerLoading from './drawer_loading';
import BundleColumnError from './bundle_column_error';
-import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, FavouritedStatuses, ListTimeline } from '../../ui/util/async-components';
+import { Compose, Notifications, HomeTimeline, CommunityTimeline, PublicTimeline, HashtagTimeline, DirectTimeline, FavouritedStatuses, ListTimeline } from '../../ui/util/async-components';
import detectPassiveEvents from 'detect-passive-events';
import { scrollRight } from '../../../scroll';
@@ -24,6 +24,7 @@ const componentMap = {
'PUBLIC': PublicTimeline,
'COMMUNITY': CommunityTimeline,
'HASHTAG': HashtagTimeline,
+ 'DIRECT': DirectTimeline,
'FAVOURITES': FavouritedStatuses,
'LIST': ListTimeline,
};
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index d2ef19e47..adca0d617 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -30,6 +30,7 @@ import {
Following,
Reblogs,
Favourites,
+ DirectTimeline,
HashtagTimeline,
Notifications,
FollowRequests,
@@ -79,6 +80,7 @@ const keyMap = {
goToNotifications: 'g n',
goToLocal: 'g l',
goToFederated: 'g t',
+ goToDirect: 'g d',
goToStart: 'g s',
goToFavourites: 'g f',
goToPinned: 'g p',
@@ -140,6 +142,7 @@ class SwitchingColumnsArea extends React.PureComponent {
+
@@ -386,6 +389,10 @@ export default class UI extends React.PureComponent {
this.context.router.history.push('/timelines/public');
}
+ handleHotkeyGoToDirect = () => {
+ this.context.router.history.push('/timelines/direct');
+ }
+
handleHotkeyGoToStart = () => {
this.context.router.history.push('/getting-started');
}
@@ -425,6 +432,7 @@ export default class UI extends React.PureComponent {
goToNotifications: this.handleHotkeyGoToNotifications,
goToLocal: this.handleHotkeyGoToLocal,
goToFederated: this.handleHotkeyGoToFederated,
+ goToDirect: this.handleHotkeyGoToDirect,
goToStart: this.handleHotkeyGoToStart,
goToFavourites: this.handleHotkeyGoToFavourites,
goToPinned: this.handleHotkeyGoToPinned,
diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js
index 19957208f..8cf2a6e7d 100644
--- a/app/javascript/mastodon/features/ui/util/async-components.js
+++ b/app/javascript/mastodon/features/ui/util/async-components.js
@@ -26,6 +26,10 @@ export function HashtagTimeline () {
return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline');
}
+export function DirectTimeline() {
+ return import(/* webpackChunkName: "features/direct_timeline" */'../../direct_timeline');
+}
+
export function ListTimeline () {
return import(/* webpackChunkName: "features/list_timeline" */'../../list_timeline');
}
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index c13ff773d..24c8a5b54 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "إعادة المحاولة",
"column.blocks": "الحسابات المحجوبة",
"column.community": "الخيط العام المحلي",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "المفضلة",
"column.follow_requests": "طلبات المتابعة",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "رموز",
"emoji_button.travel": "أماكن و أسفار",
"empty_column.community": "الخط الزمني المحلي فارغ. أكتب شيئا ما للعامة كبداية !",
+ "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": "ليس هناك بعدُ أي محتوى ذو علاقة بهذا الوسم.",
"empty_column.home": "إنك لا تتبع بعد أي شخص إلى حد الآن. زر {public} أو استخدام حقل البحث لكي تبدأ على التعرف على مستخدمين آخرين.",
"empty_column.home.public_timeline": "الخيط العام",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "هل تود إخفاء الإخطارات القادمة من هذا المستخدم ؟",
"navigation_bar.blocks": "الحسابات المحجوبة",
"navigation_bar.community_timeline": "الخيط العام المحلي",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "تعديل الملف الشخصي",
"navigation_bar.favourites": "المفضلة",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} و {results}}",
"standalone.public_title": "نظرة على ...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "تعذرت ترقية هذا المنشور",
"status.delete": "إحذف",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "تدبيس على الملف الشخصي",
"status.pinned": "تبويق مثبَّت",
"status.reblog": "رَقِّي",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} رقى",
"status.reply": "ردّ",
"status.replyAll": "رُد على الخيط",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 981aced0b..25ef6db65 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"column.community": "Local timeline",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
@@ -100,6 +101,7 @@
"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",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.community_timeline": "Local timeline",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Редактирай профил",
"navigation_bar.favourites": "Favourites",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Изтриване",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Споделяне",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} сподели",
"status.reply": "Отговор",
"status.replyAll": "Reply to thread",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index d9270e0ce..6a44808e0 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Torna-ho a provar",
"column.blocks": "Usuaris blocats",
"column.community": "Línia de temps local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favorits",
"column.follow_requests": "Peticions per seguir-te",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Símbols",
"emoji_button.travel": "Viatges i Llocs",
"empty_column.community": "La línia de temps local és buida. Escriu alguna cosa públicament per fer rodar la pilota!",
+ "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": "Encara no hi ha res amb aquesta etiqueta.",
"empty_column.home": "Encara no segueixes ningú. Visita {public} o fes cerca per començar i conèixer altres usuaris.",
"empty_column.home.public_timeline": "la línia de temps pública",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Amagar notificacions d'aquest usuari?",
"navigation_bar.blocks": "Usuaris bloquejats",
"navigation_bar.community_timeline": "Línia de temps Local",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favorits",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, un {result} altres {results}}",
"standalone.public_title": "Una mirada a l'interior ...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Aquesta publicació no pot ser retootejada",
"status.delete": "Esborrar",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fixat en el perfil",
"status.pinned": "Toot fixat",
"status.reblog": "Impuls",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} ha retootejat",
"status.reply": "Respondre",
"status.replyAll": "Respondre al tema",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 6eb5e6840..69c2ae8d8 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Erneut versuchen",
"column.blocks": "Blockierte Profile",
"column.community": "Lokale Zeitleiste",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoriten",
"column.follow_requests": "Folgeanfragen",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symbole",
"emoji_button.travel": "Reisen und Orte",
"empty_column.community": "Die lokale Zeitleiste ist leer. Schreibe einen öffentlichen Beitrag, um den Ball ins Rollen zu bringen!",
+ "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": "Unter diesem Hashtag gibt es noch nichts.",
"empty_column.home": "Deine Startseite ist leer! Besuche {public} oder nutze die Suche, um loszulegen und andere Leute zu finden.",
"empty_column.home.public_timeline": "die öffentliche Zeitleiste",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Benachrichtigungen von diesem Account verbergen?",
"navigation_bar.blocks": "Blockierte Profile",
"navigation_bar.community_timeline": "Lokale Zeitleiste",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Profil bearbeiten",
"navigation_bar.favourites": "Favoriten",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {Ergebnis} other {Ergebnisse}}",
"standalone.public_title": "Ein kleiner Einblick …",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Dieser Beitrag kann nicht geteilt werden",
"status.delete": "Löschen",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Im Profil anheften",
"status.pinned": "Pinned toot",
"status.reblog": "Teilen",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} teilte",
"status.reply": "Antworten",
"status.replyAll": "Auf Thread antworten",
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index a3c4f775c..5a02e0c72 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -242,6 +242,14 @@
"defaultMessage": "Boost",
"id": "status.reblog"
},
+ {
+ "defaultMessage": "Boost to original audience",
+ "id": "status.reblog_private"
+ },
+ {
+ "defaultMessage": "Unboost",
+ "id": "status.cancel_reblog_private"
+ },
{
"defaultMessage": "This post cannot be boosted",
"id": "status.cannot_reblog"
@@ -897,6 +905,19 @@
],
"path": "app/javascript/mastodon/features/compose/index.json"
},
+ {
+ "descriptors": [
+ {
+ "defaultMessage": "Direct messages",
+ "id": "column.direct"
+ },
+ {
+ "defaultMessage": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
+ "id": "empty_column.direct"
+ }
+ ],
+ "path": "app/javascript/mastodon/features/direct_timeline/index.json"
+ },
{
"descriptors": [
{
@@ -971,6 +992,10 @@
"defaultMessage": "Local timeline",
"id": "navigation_bar.community_timeline"
},
+ {
+ "defaultMessage": "Direct messages",
+ "id": "navigation_bar.direct"
+ },
{
"defaultMessage": "Preferences",
"id": "navigation_bar.preferences"
@@ -1399,6 +1424,14 @@
"defaultMessage": "Boost",
"id": "status.reblog"
},
+ {
+ "defaultMessage": "Boost to original audience",
+ "id": "status.reblog_private"
+ },
+ {
+ "defaultMessage": "Unboost",
+ "id": "status.cancel_reblog_private"
+ },
{
"defaultMessage": "This post cannot be boosted",
"id": "status.cannot_reblog"
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index a389735c1..d8bd7e3e0 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"column.community": "Local timeline",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
@@ -100,6 +101,7 @@
"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",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.community_timeline": "Local timeline",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Edit profile",
"navigation_bar.favourites": "Favourites",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Delete",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Boost",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index 19f3c5907..e51163971 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Bonvolu reprovi",
"column.blocks": "Blokitaj uzantoj",
"column.community": "Loka tempolinio",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Stelumoj",
"column.follow_requests": "Petoj de sekvado",
@@ -100,6 +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.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",
@@ -154,6 +156,7 @@
"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.edit_profile": "Redakti profilon",
"navigation_bar.favourites": "Stelumoj",
@@ -238,6 +241,7 @@
"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.cannot_reblog": "Ĉi tiu mesaĝo ne diskonigeblas",
"status.delete": "Forigi",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Alpingli profile",
"status.pinned": "Alpinglita mesaĝo",
"status.reblog": "Diskonigi",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} diskonigis",
"status.reply": "Respondi",
"status.replyAll": "Respondi al la fadeno",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index e765cc078..61ea0588d 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Inténtalo de nuevo",
"column.blocks": "Usuarios bloqueados",
"column.community": "Línea de tiempo local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoritos",
"column.follow_requests": "Solicitudes de seguimiento",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viajes y lugares",
"empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
+ "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": "No hay nada en este hashtag aún.",
"empty_column.home": "No estás siguiendo a nadie aún. Visita {public} o haz búsquedas para empezar y conocer gente nueva.",
"empty_column.home.public_timeline": "la línea de tiempo pública",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Ocultar notificaciones de este usuario?",
"navigation_bar.blocks": "Usuarios bloqueados",
"navigation_bar.community_timeline": "Historia local",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favoritos",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Un pequeño vistazo...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Este toot no puede retootearse",
"status.delete": "Borrar",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fijar",
"status.pinned": "Toot fijado",
"status.reblog": "Retootear",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "Retooteado por {name}",
"status.reply": "Responder",
"status.replyAll": "Responder al hilo",
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index 822c998ce..cfe93007d 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "تلاش دوباره",
"column.blocks": "کاربران مسدودشده",
"column.community": "نوشتههای محلی",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "پسندیدهها",
"column.follow_requests": "درخواستهای پیگیری",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "نمادها",
"emoji_button.travel": "سفر و مکان",
"empty_column.community": "فهرست نوشتههای محلی خالی است. چیزی بنویسید تا چرخش بچرخد!",
+ "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": "هنوز هیچ چیزی با این هشتگ نیست.",
"empty_column.home": "شما هنوز پیگیر کسی نیستید. {public} را ببینید یا چیزی را جستجو کنید تا کاربران دیگر را ببینید.",
"empty_column.home.public_timeline": "فهرست نوشتههای همهجا",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "اعلانهای این کاربر پنهان شود؟",
"navigation_bar.blocks": "کاربران مسدودشده",
"navigation_bar.community_timeline": "نوشتههای محلی",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "ویرایش نمایه",
"navigation_bar.favourites": "پسندیدهها",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {نتیجه} other {نتیجه}}",
"standalone.public_title": "نگاهی به کاربران این سرور...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "این نوشته را نمیشود بازبوقید",
"status.delete": "پاککردن",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "نوشتهٔ ثابت نمایه",
"status.pinned": "Pinned toot",
"status.reblog": "بازبوقیدن",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} بازبوقید",
"status.reply": "پاسخ",
"status.replyAll": "به نوشته پاسخ دهید",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 5763ac442..1677c3c6c 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Yritä uudestaan",
"column.blocks": "Estetyt käyttäjät",
"column.community": "Paikallinen aikajana",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Suosikit",
"column.follow_requests": "Seuraamispyynnöt",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symbolit",
"emoji_button.travel": "Matkailu",
"empty_column.community": "Paikallinen aikajana on tyhjä. Homma lähtee käyntiin, kun kirjoitat jotain julkista!",
+ "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": "Tällä hashtagilla ei ole vielä mitään.",
"empty_column.home": "Kotiaikajanasi on tyhjä! {public} ja hakutoiminto auttavat alkuun ja kohtaamaan muita käyttäjiä.",
"empty_column.home.public_timeline": "yleinen aikajana",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Piilota tältä käyttäjältä tulevat ilmoitukset?",
"navigation_bar.blocks": "Estetyt käyttäjät",
"navigation_bar.community_timeline": "Paikallinen aikajana",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Muokkaa profiilia",
"navigation_bar.favourites": "Suosikit",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "Kurkistus sisälle...",
"status.block": "Estä @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Tätä julkaisua ei voi buustata",
"status.delete": "Poista",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Kiinnitä profiiliin",
"status.pinned": "Kiinnitetty tuuttaus",
"status.reblog": "Buustaa",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} buustasi",
"status.reply": "Vastaa",
"status.replyAll": "Vastaa ketjuun",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index ef1c115e3..98c1c43d2 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Réessayer",
"column.blocks": "Comptes bloqués",
"column.community": "Fil public local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoris",
"column.follow_requests": "Demandes de suivi",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symboles",
"emoji_button.travel": "Lieux & Voyages",
"empty_column.community": "Le fil public local est vide. Écrivez donc quelque chose pour le remplir !",
+ "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": "Il n’y a encore aucun contenu associé à ce hashtag.",
"empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres personnes.",
"empty_column.home.public_timeline": "le fil public",
@@ -154,6 +156,7 @@
"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": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Modifier le profil",
"navigation_bar.favourites": "Favoris",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}",
"standalone.public_title": "Un aperçu …",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Cette publication ne peut être boostée",
"status.delete": "Effacer",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Épingler sur le profil",
"status.pinned": "Pouet épinglé",
"status.reblog": "Partager",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} a partagé :",
"status.reply": "Répondre",
"status.replyAll": "Répondre au fil",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index 5cbb7d31d..fca42374d 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Inténteo de novo",
"column.blocks": "Usuarias bloqueadas",
"column.community": "Liña temporal local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoritas",
"column.follow_requests": "Peticións de seguimento",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viaxes e Lugares",
"empty_column.community": "A liña temporal local está baldeira. Escriba algo de xeito público para que rule!",
+ "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": "Aínda non hai nada con esta etiqueta.",
"empty_column.home": "A súa liña temporal de inicio está baldeira! Visite {public} ou utilice a busca para atopar outras usuarias.",
"empty_column.home.public_timeline": "a liña temporal pública",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Esconder notificacións deste usuario?",
"navigation_bar.blocks": "Usuarias bloqueadas",
"navigation_bar.community_timeline": "Liña temporal local",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favoritas",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count,plural,one {result} outros {results}}",
"standalone.public_title": "Ollada dentro...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Esta mensaxe non pode ser promocionada",
"status.delete": "Eliminar",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fixar no perfil",
"status.pinned": "Pinned toot",
"status.reblog": "Promover",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} promoveu",
"status.reply": "Resposta",
"status.replyAll": "Resposta a conversa",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 656d93cdf..e3e87f1d0 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "לנסות שוב",
"column.blocks": "חסימות",
"column.community": "ציר זמן מקומי",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "חיבובים",
"column.follow_requests": "בקשות מעקב",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "סמלים",
"emoji_button.travel": "טיולים ואתרים",
"empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתרחילו להתגלגל!",
+ "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": "אין כלום בהאשתג הזה עדיין.",
"empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר חצוצרנים אחרים.",
"empty_column.home.public_timeline": "ציר זמן בין-קהילתי",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "להסתיר הודעות מחשבון זה?",
"navigation_bar.blocks": "חסימות",
"navigation_bar.community_timeline": "ציר זמן מקומי",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "עריכת פרופיל",
"navigation_bar.favourites": "חיבובים",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}",
"standalone.public_title": "הצצה פנימה...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "לא ניתן להדהד הודעה זו",
"status.delete": "מחיקה",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "לקבע באודות",
"status.pinned": "Pinned toot",
"status.reblog": "הדהוד",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "הודהד על ידי {name}",
"status.reply": "תגובה",
"status.replyAll": "תגובה לכולם",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index 2d7d0a5a4..b41c98394 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blokirani korisnici",
"column.community": "Lokalni timeline",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoriti",
"column.follow_requests": "Zahtjevi za slijeđenje",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Simboli",
"emoji_button.travel": "Putovanja & Mjesta",
"empty_column.community": "Lokalni timeline je prazan. Napiši nešto javno kako bi pokrenuo stvari!",
+ "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": "Još ne postoji ništa s ovim hashtagom.",
"empty_column.home": "Još ne slijediš nikoga. Posjeti {public} ili koristi tražilicu kako bi počeo i upoznao druge korisnike.",
"empty_column.home.public_timeline": "javni timeline",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Blokirani korisnici",
"navigation_bar.community_timeline": "Lokalni timeline",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Uredi profil",
"navigation_bar.favourites": "Favoriti",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Ovaj post ne može biti boostan",
"status.delete": "Obriši",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Podigni",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} je podigao",
"status.reply": "Odgovori",
"status.replyAll": "Odgovori na temu",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 24f3a7816..956accc67 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Próbálja újra",
"column.blocks": "Letiltott felhasználók",
"column.community": "Helyi idővonal",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Kedvencek",
"column.follow_requests": "Követési kérések",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Szimbólumok",
"emoji_button.travel": "Utazás és Helyek",
"empty_column.community": "A helyi idővonal üres. Írj egy publikus stástuszt, hogy elindítsd a labdát!",
+ "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": "Jelenleg nem található semmi ezen hashtaggel.",
"empty_column.home": "A hazai idővonala üres! Látogasd meg a {public} vagy használd a keresőt, hogy ismerj meg más felhasználókat.",
"empty_column.home.public_timeline": "publikus idővonal",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Értesítések elrejtése ezen felhasználótól?",
"navigation_bar.blocks": "Tiltott felhasználók",
"navigation_bar.community_timeline": "Helyi idővonal",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Profil szerkesztése",
"navigation_bar.favourites": "Kedvencek",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "Betekintés...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Ezen státusz nem rebloggolható",
"status.delete": "Törlés",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Kitűzés a profilra",
"status.pinned": "Pinned toot",
"status.reblog": "Reblog",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} reblogolta",
"status.reply": "Válasz",
"status.replyAll": "Válaszolj a beszélgetésre",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 2ba52c5c0..33e079201 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Կրկին փորձել",
"column.blocks": "Արգելափակված օգտատերեր",
"column.community": "Տեղական հոսք",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Հավանածներ",
"column.follow_requests": "Հետեւելու հայցեր",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Նշաններ",
"emoji_button.travel": "Ուղեւորություն եւ տեղանքներ",
"empty_column.community": "Տեղական հոսքը դատա՛րկ է։ Հրապարակային մի բան գրիր շարժիչը խոդ տալու համար։",
+ "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": "Այս պիտակով դեռ ոչինչ չկա։",
"empty_column.home": "Քո հիմնական հոսքը դատա՛րկ է։ Այցելի՛ր {public}ը կամ օգտվիր որոնումից՝ այլ մարդկանց հանդիպելու համար։",
"empty_column.home.public_timeline": "հրապարակային հոսք",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Թաքցնե՞լ ցանուցումներն այս օգտատիրոջից։",
"navigation_bar.blocks": "Արգելափակված օգտատերեր",
"navigation_bar.community_timeline": "Տեղական հոսք",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Խմբագրել անձնական էջը",
"navigation_bar.favourites": "Հավանածներ",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "Այս պահին…",
"status.block": "Արգելափակել @{name}֊ին",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Այս թութը չի կարող տարածվել",
"status.delete": "Ջնջել",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Ամրացնել անձնական էջում",
"status.pinned": "Pinned toot",
"status.reblog": "Տարածել",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} տարածել է",
"status.reply": "Պատասխանել",
"status.replyAll": "Պատասխանել թելին",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index e1518c1aa..412ffd3a0 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Coba lagi",
"column.blocks": "Pengguna diblokir",
"column.community": "Linimasa Lokal",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favorit",
"column.follow_requests": "Permintaan mengikuti",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Simbol",
"emoji_button.travel": "Tempat Wisata",
"empty_column.community": "Linimasa lokal masih kosong. Tulis sesuatu secara publik dan buat roda berputar!",
+ "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": "Tidak ada apapun dalam hashtag ini.",
"empty_column.home": "Linimasa anda kosong! Kunjungi {public} atau gunakan pencarian untuk memulai dan bertemu pengguna lain.",
"empty_column.home.public_timeline": "linimasa publik",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Pengguna diblokir",
"navigation_bar.community_timeline": "Linimasa lokal",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Ubah profil",
"navigation_bar.favourites": "Favorit",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {hasil} other {hasil}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Hapus",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Boost",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "di-boost {name}",
"status.reply": "Balas",
"status.replyAll": "Balas ke semua",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index c79d4a634..9730bf934 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blokusita uzeri",
"column.community": "Lokala tempolineo",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favorati",
"column.follow_requests": "Demandi di sequado",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.community": "La lokala tempolineo esas vakua. Skribez ulo publike por iniciar la agiveso!",
+ "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": "Esas ankore nulo en ta gretovorto.",
"empty_column.home": "Tu sequas ankore nulu. Vizitez {public} od uzez la serchilo por komencar e renkontrar altra uzeri.",
"empty_column.home.public_timeline": "la publika tempolineo",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Blokusita uzeri",
"navigation_bar.community_timeline": "Lokala tempolineo",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Modifikar profilo",
"navigation_bar.favourites": "Favorati",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {rezulto} other {rezulti}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Efacar",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Repetar",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} repetita",
"status.reply": "Respondar",
"status.replyAll": "Respondar a filo",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 3c85a3e20..5146d7ca2 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Utenti bloccati",
"column.community": "Timeline locale",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Apprezzati",
"column.follow_requests": "Richieste di amicizia",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.community": "La timeline locale è vuota. Condividi qualcosa pubblicamente per dare inizio alla festa!",
+ "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": "Non c'è ancora nessun post con questo hashtag.",
"empty_column.home": "Non stai ancora seguendo nessuno. Visita {public} o usa la ricerca per incontrare nuove persone.",
"empty_column.home.public_timeline": "la timeline pubblica",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Utenti bloccati",
"navigation_bar.community_timeline": "Timeline locale",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Modifica profilo",
"navigation_bar.favourites": "Apprezzati",
@@ -238,6 +241,7 @@
"search_results.total": "{count} {count, plural, one {risultato} other {risultati}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Elimina",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Condividi",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} ha condiviso",
"status.reply": "Rispondi",
"status.replyAll": "Reply to thread",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 2da9192ca..a4aa06a06 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "再試行",
"column.blocks": "ブロックしたユーザー",
"column.community": "ローカルタイムライン",
+ "column.direct": "Direct messages",
"column.domain_blocks": "非表示にしたドメイン",
"column.favourites": "お気に入り",
"column.follow_requests": "フォローリクエスト",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "記号",
"emoji_button.travel": "旅行と場所",
"empty_column.community": "ローカルタイムラインはまだ使われていません。何か書いてみましょう!",
+ "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": "このハッシュタグはまだ使われていません。",
"empty_column.home": "まだ誰もフォローしていません。{public}を見に行くか、検索を使って他のユーザーを見つけましょう。",
"empty_column.home.public_timeline": "連合タイムライン",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "このユーザーからの通知を隠しますか?",
"navigation_bar.blocks": "ブロックしたユーザー",
"navigation_bar.community_timeline": "ローカルタイムライン",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "非表示にしたドメイン",
"navigation_bar.edit_profile": "プロフィールを編集",
"navigation_bar.favourites": "お気に入り",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number}件の結果",
"standalone.public_title": "今こんな話をしています...",
"status.block": "@{name}さんをブロック",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "この投稿はブーストできません",
"status.delete": "削除",
"status.direct": "@{name}さんにダイレクトメッセージ",
@@ -253,6 +257,7 @@
"status.pin": "プロフィールに固定表示",
"status.pinned": "固定されたトゥート",
"status.reblog": "ブースト",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name}さんがブースト",
"status.reply": "返信",
"status.replyAll": "全員に返信",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index e2fadff3c..92367dc95 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "다시 시도",
"column.blocks": "차단 중인 사용자",
"column.community": "로컬 타임라인",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "즐겨찾기",
"column.follow_requests": "팔로우 요청",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "기호",
"emoji_button.travel": "여행과 장소",
"empty_column.community": "로컬 타임라인에 아무 것도 없습니다. 아무거나 적어 보세요!",
+ "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": "이 해시태그는 아직 사용되지 않았습니다.",
"empty_column.home": "아직 아무도 팔로우 하고 있지 않습니다. {public}를 보러 가거나, 검색하여 다른 사용자를 찾아 보세요.",
"empty_column.home.public_timeline": "연합 타임라인",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "이 사용자로부터의 알림을 뮤트하시겠습니까?",
"navigation_bar.blocks": "차단한 사용자",
"navigation_bar.community_timeline": "로컬 타임라인",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "프로필 편집",
"navigation_bar.favourites": "즐겨찾기",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number}건의 결과",
"standalone.public_title": "지금 이런 이야기를 하고 있습니다…",
"status.block": "@{name} 차단",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "이 포스트는 부스트 할 수 없습니다",
"status.delete": "삭제",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "고정",
"status.pinned": "고정 된 툿",
"status.reblog": "부스트",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name}님이 부스트 했습니다",
"status.reply": "답장",
"status.replyAll": "전원에게 답장",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index 0222432a0..c18ddbd01 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Opnieuw proberen",
"column.blocks": "Geblokkeerde gebruikers",
"column.community": "Lokale tijdlijn",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favorieten",
"column.follow_requests": "Volgverzoeken",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symbolen",
"emoji_button.travel": "Reizen en plekken",
"empty_column.community": "De lokale tijdlijn is nog leeg. Toot iets in het openbaar om de bal aan het rollen te krijgen!",
+ "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": "Er is nog niks te vinden onder deze hashtag.",
"empty_column.home": "Jij volgt nog niemand. Bezoek {public} of gebruik het zoekvenster om andere mensen te ontmoeten.",
"empty_column.home.public_timeline": "de globale tijdlijn",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Verberg meldingen van deze persoon?",
"navigation_bar.blocks": "Geblokkeerde gebruikers",
"navigation_bar.community_timeline": "Lokale tijdlijn",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Profiel bewerken",
"navigation_bar.favourites": "Favorieten",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {resultaat} other {resultaten}}",
"standalone.public_title": "Een kijkje binnenin...",
"status.block": "Blokkeer @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Deze toot kan niet geboost worden",
"status.delete": "Verwijderen",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Aan profielpagina vastmaken",
"status.pinned": "Vastgemaakte toot",
"status.reblog": "Boost",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boostte",
"status.reply": "Reageren",
"status.replyAll": "Reageer op iedereen",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 20b2cbb26..282a72acb 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Prøv igjen",
"column.blocks": "Blokkerte brukere",
"column.community": "Lokal tidslinje",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Likt",
"column.follow_requests": "Følgeforespørsler",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symboler",
"emoji_button.travel": "Reise & steder",
"empty_column.community": "Den lokale tidslinjen er tom. Skriv noe offentlig for å få snøballen til å rulle!",
+ "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": "Det er ingenting i denne hashtagen ennå.",
"empty_column.home": "Du har ikke fulgt noen ennå. Besøk {publlic} eller bruk søk for å komme i gang og møte andre brukere.",
"empty_column.home.public_timeline": "en offentlig tidslinje",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Skjul varslinger fra denne brukeren?",
"navigation_bar.blocks": "Blokkerte brukere",
"navigation_bar.community_timeline": "Lokal tidslinje",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Rediger profil",
"navigation_bar.favourites": "Favoritter",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultater}}",
"standalone.public_title": "En titt inni...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Denne posten kan ikke fremheves",
"status.delete": "Slett",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fest på profilen",
"status.pinned": "Pinned toot",
"status.reblog": "Fremhev",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "Fremhevd av {name}",
"status.reply": "Svar",
"status.replyAll": "Svar til samtale",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 32133c1f4..7170aefb8 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Tornar ensajar",
"column.blocks": "Personas blocadas",
"column.community": "Flux public local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favorits",
"column.follow_requests": "Demandas d’abonament",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Simbòls",
"emoji_button.travel": "Viatges & lòcs",
"empty_column.community": "Lo flux public local es void. Escrivètz quicòm per lo garnir !",
+ "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": "I a pas encara de contengut ligat a aquesta etiqueta.",
"empty_column.home": "Vòstre flux d’acuèlh es void. Visitatz {public} o utilizatz la recèrca per vos connectar a d’autras personas.",
"empty_column.home.public_timeline": "lo flux public",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Rescondre las notificacions d’aquesta persona ?",
"navigation_bar.blocks": "Personas blocadas",
"navigation_bar.community_timeline": "Flux public local",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Modificar lo perfil",
"navigation_bar.favourites": "Favorits",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}",
"standalone.public_title": "Una ulhada dedins…",
"status.block": "Blocar @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Aqueste estatut pòt pas èsser partejat",
"status.delete": "Escafar",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Penjar al perfil",
"status.pinned": "Tut penjat",
"status.reblog": "Partejar",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} a partejat",
"status.reply": "Respondre",
"status.replyAll": "Respondre a la conversacion",
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 5360b6f33..c55603a99 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Spróbuj ponownie",
"column.blocks": "Zablokowani użytkownicy",
"column.community": "Lokalna oś czasu",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Ukryte domeny",
"column.favourites": "Ulubione",
"column.follow_requests": "Prośby o śledzenie",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symbole",
"emoji_button.travel": "Podróże i miejsca",
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
+ "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": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy!",
"empty_column.home": "Nie śledzisz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
"empty_column.home.public_timeline": "publiczna oś czasu",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Chcesz ukryć powiadomienia od tego użytkownika?",
"navigation_bar.blocks": "Zablokowani użytkownicy",
"navigation_bar.community_timeline": "Lokalna oś czasu",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Ukryte domeny",
"navigation_bar.edit_profile": "Edytuj profil",
"navigation_bar.favourites": "Ulubione",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {wynik} few {wyniki} many {wyników} more {wyników}}",
"standalone.public_title": "Spojrzenie w głąb…",
"status.block": "Zablokuj @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Ten wpis nie może zostać podbity",
"status.delete": "Usuń",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Przypnij do profilu",
"status.pinned": "Przypięty wpis",
"status.reblog": "Podbij",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} podbił",
"status.reply": "Odpowiedz",
"status.replyAll": "Odpowiedz na wątek",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index b4be0bbc7..c604476c7 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Tente novamente",
"column.blocks": "Usuários bloqueados",
"column.community": "Local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoritos",
"column.follow_requests": "Seguidores pendentes",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viagens & Lugares",
"empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!",
+ "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": "Ainda não há qualquer conteúdo com essa hashtag.",
"empty_column.home": "Você ainda não segue usuário algum. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.",
"empty_column.home.public_timeline": "global",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Esconder notificações deste usuário?",
"navigation_bar.blocks": "Usuários bloqueados",
"navigation_bar.community_timeline": "Local",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favoritos",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Dê uma espiada...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Esta postagem não pode ser compartilhada",
"status.delete": "Excluir",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fixar no perfil",
"status.pinned": "Toot fixado",
"status.reblog": "Compartilhar",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} compartilhou",
"status.reply": "Responder",
"status.replyAll": "Responder à sequência",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index 132de5293..826785aad 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Tente de novo",
"column.blocks": "Utilizadores Bloqueados",
"column.community": "Local",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoritos",
"column.follow_requests": "Seguidores Pendentes",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viagens & Lugares",
"empty_column.community": "Ainda não existe conteúdo local para mostrar!",
+ "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": "Não foram encontradas publicações com essa hashtag.",
"empty_column.home": "Ainda não segues qualquer utilizador. Visita {public} ou utiliza a pesquisa para procurar outros utilizadores.",
"empty_column.home.public_timeline": "global",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Esconder notificações deste utilizador?",
"navigation_bar.blocks": "Utilizadores bloqueados",
"navigation_bar.community_timeline": "Local",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favoritos",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Espreitar lá dentro...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Este post não pode ser partilhado",
"status.delete": "Eliminar",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fixar no perfil",
"status.pinned": "Pinned toot",
"status.reblog": "Partilhar",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} partilhou",
"status.reply": "Responder",
"status.replyAll": "Responder à conversa",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index b56ccf1df..bb3cc1794 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Попробовать снова",
"column.blocks": "Список блокировки",
"column.community": "Локальная лента",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Скрытые домены",
"column.favourites": "Понравившееся",
"column.follow_requests": "Запросы на подписку",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Символы",
"emoji_button.travel": "Путешествия",
"empty_column.community": "Локальная лента пуста. Напишите что-нибудь, чтобы разогреть народ!",
+ "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": "Статусов с таким хэштегом еще не существует.",
"empty_column.home": "Пока Вы ни на кого не подписаны. Полистайте {public} или используйте поиск, чтобы освоиться и завести новые знакомства.",
"empty_column.home.public_timeline": "публичные ленты",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Убрать уведомления от этого пользователя?",
"navigation_bar.blocks": "Список блокировки",
"navigation_bar.community_timeline": "Локальная лента",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Скрытые домены",
"navigation_bar.edit_profile": "Изменить профиль",
"navigation_bar.favourites": "Понравившееся",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {результат} few {результата} many {результатов} other {результатов}}",
"standalone.public_title": "Прямо сейчас",
"status.block": "Заблокировать @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Этот статус не может быть продвинут",
"status.delete": "Удалить",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Закрепить в профиле",
"status.pinned": "Pinned toot",
"status.reblog": "Продвинуть",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} продвинул(а)",
"status.reply": "Ответить",
"status.replyAll": "Ответить на тред",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 159315137..58274fd2d 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Skúsiť znova",
"column.blocks": "Blokovaní užívatelia",
"column.community": "Lokálna časová os",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Obľúbené",
"column.follow_requests": "Žiadosti o sledovanie",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symboly",
"emoji_button.travel": "Cestovanie a miesta",
"empty_column.community": "Lokálna časová os je prázdna. Napíšte niečo, aby sa to tu začalo hýbať!",
+ "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": "Pod týmto hashtagom sa ešte nič nenachádza.",
"empty_column.home": "Vaša lokálna osa je zatiaľ prázdna! Pre začiatok pozrite {public} alebo použite vyhľadávanie a nájdite tak ostatných používateľov.",
"empty_column.home.public_timeline": "verejná časová os",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Skryť notifikácie od tohoto užívateľa?",
"navigation_bar.blocks": "Blokovaní užívatelia",
"navigation_bar.community_timeline": "Lokálna časová os",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Upraviť profil",
"navigation_bar.favourites": "Obľúbené",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, jeden {výsledok} ostatné {výsledky}}",
"standalone.public_title": "Náhľad dovnútra...",
"status.block": "Blokovať @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
"status.delete": "Zmazať",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pripni na profil",
"status.pinned": "Pripnutý príspevok",
"status.reblog": "Povýšiť",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} povýšil/a",
"status.reply": "Odpovedať",
"status.replyAll": "Odpovedať na diskusiu",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index 69c7aa62b..e4d07edd1 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Pokušajte ponovo",
"column.blocks": "Blokirani korisnici",
"column.community": "Lokalna lajna",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Omiljeni",
"column.follow_requests": "Zahtevi za praćenje",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Simboli",
"emoji_button.travel": "Putovanja & mesta",
"empty_column.community": "Lokalna lajna je prazna. Napišite nešto javno da lajna produva!",
+ "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": "Trenutno nema ništa na ovom heštegu.",
"empty_column.home": "Vaša lajna je prazna! Posetite {public} ili koristite pretragu da počnete i upoznajete nove ljude.",
"empty_column.home.public_timeline": "javna lajna",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Sakrij obaveštenja od ovog korisnika?",
"navigation_bar.blocks": "Blokirani korisnici",
"navigation_bar.community_timeline": "Lokalna lajna",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Izmeni profil",
"navigation_bar.favourites": "Omiljeni",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {rezultat} few {rezultata} other {rezultata}}",
"standalone.public_title": "Pogled iznutra...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Ovaj status ne može da se podrži",
"status.delete": "Obriši",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Prikači na profil",
"status.pinned": "Pinned toot",
"status.reblog": "Podrži",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} podržao(la)",
"status.reply": "Odgovori",
"status.replyAll": "Odgovori na diskusiju",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index e9739451e..60c781e9d 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Покушајте поново",
"column.blocks": "Блокирани корисници",
"column.community": "Локална лајна",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Омиљени",
"column.follow_requests": "Захтеви за праћење",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Симболи",
"emoji_button.travel": "Путовања & места",
"empty_column.community": "Локална лајна је празна. Напишите нешто јавно да лајна продува!",
+ "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": "Тренутно нема ништа на овом хештегу.",
"empty_column.home": "Ваша лајна је празна! Посетите {public} или користите претрагу да почнете и упознајете нове људе.",
"empty_column.home.public_timeline": "јавна лајна",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Сакриј обавештења од овог корисника?",
"navigation_bar.blocks": "Блокирани корисници",
"navigation_bar.community_timeline": "Локална лајна",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Измени профил",
"navigation_bar.favourites": "Омиљени",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {резултат} few {резултата} other {резултата}}",
"standalone.public_title": "Поглед изнутра...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Овај статус не може да се подржи",
"status.delete": "Обриши",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Прикачи на профил",
"status.pinned": "Pinned toot",
"status.reblog": "Подржи",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} подржао(ла)",
"status.reply": "Одговори",
"status.replyAll": "Одговори на дискусију",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index b063adb0f..8fa6992f1 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Försök igen",
"column.blocks": "Blockerade användare",
"column.community": "Lokal tidslinje",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoriter",
"column.follow_requests": "Följ förfrågningar",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Symboler",
"emoji_button.travel": "Resor & Platser",
"empty_column.community": "Den lokala tidslinjen är tom. Skriv något offentligt för att få bollen att rulla!",
+ "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": "Det finns inget i denna hashtag ännu.",
"empty_column.home": "Din hemma-tidslinje är tom! Besök {public} eller använd sökning för att komma igång och träffa andra användare.",
"empty_column.home.public_timeline": "den publika tidslinjen",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Dölj notifikationer från denna användare?",
"navigation_bar.blocks": "Blockerade användare",
"navigation_bar.community_timeline": "Lokal tidslinje",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Redigera profil",
"navigation_bar.favourites": "Favoriter",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, ett {result} andra {results}}",
"standalone.public_title": "En titt inuti...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Detta inlägg kan inte knuffas",
"status.delete": "Ta bort",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Fäst i profil",
"status.pinned": "Fäst toot",
"status.reblog": "Knuff",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} knuffade",
"status.reply": "Svara",
"status.replyAll": "Svara på tråden",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 22a75c237..3b91c0d2c 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"column.community": "Local timeline",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
@@ -100,6 +101,7 @@
"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",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.community_timeline": "Local timeline",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Edit profile",
"navigation_bar.favourites": "Favourites",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Delete",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Boost",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index 8e36c512f..cdf6f46a3 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Engellenen kullanıcılar",
"column.community": "Yerel zaman tüneli",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favoriler",
"column.follow_requests": "Takip istekleri",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Semboller",
"emoji_button.travel": "Seyahat ve Yerler",
"empty_column.community": "Yerel zaman tüneliniz boş. Daha fazla eğlence için herkese açık bir gönderi paylaşın.",
+ "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": "Henüz bu hashtag’e sahip hiçbir gönderi yok.",
"empty_column.home": "Henüz kimseyi takip etmiyorsunuz. {public} ziyaret edebilir veya arama kısmını kullanarak diğer kullanıcılarla iletişime geçebilirsiniz.",
"empty_column.home.public_timeline": "herkese açık zaman tüneli",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Engellenen kullanıcılar",
"navigation_bar.community_timeline": "Yerel zaman tüneli",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Profili düzenle",
"navigation_bar.favourites": "Favoriler",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuçlar}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Bu gönderi boost edilemez",
"status.delete": "Sil",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Boost'la",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boost etti",
"status.reply": "Cevapla",
"status.replyAll": "Konuşmayı cevapla",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 09210a325..261e5795e 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "Try again",
"column.blocks": "Заблоковані користувачі",
"column.community": "Локальна стрічка",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Вподобане",
"column.follow_requests": "Запити на підписку",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "Символи",
"emoji_button.travel": "Подорожі",
"empty_column.community": "Локальна стрічка пуста. Напишіть щось, щоб розігріти народ!",
+ "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": "Дописів з цим хештегом поки не існує.",
"empty_column.home": "Ви поки ні на кого не підписані. Погортайте {public}, або скористуйтесь пошуком, щоб освоїтися та познайомитися з іншими користувачами.",
"empty_column.home.public_timeline": "публічні стрічки",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Заблоковані користувачі",
"navigation_bar.community_timeline": "Локальна стрічка",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Редагувати профіль",
"navigation_bar.favourites": "Вподобане",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} {count, plural, one {результат} few {результати} many {результатів} other {результатів}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Цей допис не може бути передмухнутий",
"status.delete": "Видалити",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Передмухнути",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} передмухнув(-ла)",
"status.reply": "Відповісти",
"status.replyAll": "Відповісти на тред",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index f0772ffaa..aba0bde83 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "重试",
"column.blocks": "屏蔽用户",
"column.community": "本站时间轴",
+ "column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "收藏过的嘟文",
"column.follow_requests": "关注请求",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "符号",
"emoji_button.travel": "旅行和地点",
"empty_column.community": "本站时间轴暂时没有内容,快嘟几个来抢头香啊!",
+ "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": "这个话题标签下暂时没有内容。",
"empty_column.home": "你还没有关注任何用户。快看看{public},向其他用户搭讪吧。",
"empty_column.home.public_timeline": "公共时间轴",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "同时隐藏来自这个用户的通知",
"navigation_bar.blocks": "被屏蔽的用户",
"navigation_bar.community_timeline": "本站时间轴",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "修改个人资料",
"navigation_bar.favourites": "收藏的内容",
@@ -238,6 +241,7 @@
"search_results.total": "共 {count, number} 个结果",
"standalone.public_title": "大家都在干啥?",
"status.block": "屏蔽 @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "无法转嘟这条嘟文",
"status.delete": "删除",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "在个人资料页面置顶",
"status.pinned": "Pinned toot",
"status.reblog": "转嘟",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} 转嘟了",
"status.reply": "回复",
"status.replyAll": "回复所有人",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index 28685f4d8..b5ebd20fc 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "重試",
"column.blocks": "封鎖用戶",
"column.community": "本站時間軸",
+ "column.direct": "Direct messages",
"column.domain_blocks": "隱藏的服務站",
"column.favourites": "最愛的文章",
"column.follow_requests": "關注請求",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "符號",
"emoji_button.travel": "旅遊景物",
"empty_column.community": "本站時間軸暫時未有內容,快寫一點東西來搶頭香啊!",
+ "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": "這個標籤暫時未有內容。",
"empty_column.home": "你還沒有關注任何用戶。快看看{public},向其他用戶搭訕吧。",
"empty_column.home.public_timeline": "公共時間軸",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "隱藏來自這用戶的通知嗎?",
"navigation_bar.blocks": "被你封鎖的用戶",
"navigation_bar.community_timeline": "本站時間軸",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "隱藏的服務站",
"navigation_bar.edit_profile": "修改個人資料",
"navigation_bar.favourites": "最愛的內容",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} 項結果",
"standalone.public_title": "站點一瞥…",
"status.block": "封鎖 @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "這篇文章無法被轉推",
"status.delete": "刪除",
"status.direct": "私訊 @{name}",
@@ -253,6 +257,7 @@
"status.pin": "置頂到資料頁",
"status.pinned": "置頂文章",
"status.reblog": "轉推",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} 轉推",
"status.reply": "回應",
"status.replyAll": "回應所有人",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index efed9cd4d..28d634600 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -40,6 +40,7 @@
"bundle_modal_error.retry": "重試",
"column.blocks": "封鎖的使用者",
"column.community": "本地時間軸",
+ "column.direct": "Direct messages",
"column.domain_blocks": "隱藏域名",
"column.favourites": "最愛",
"column.follow_requests": "關注請求",
@@ -100,6 +101,7 @@
"emoji_button.symbols": "符號",
"emoji_button.travel": "旅遊與地點",
"empty_column.community": "本地時間軸是空的。公開寫點什麼吧!",
+ "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": "這個主題標籤下什麼都沒有。",
"empty_column.home": "你還沒關注任何人。造訪{public}或利用搜尋功能找到其他用者。",
"empty_column.home.public_timeline": "公開時間軸",
@@ -154,6 +156,7 @@
"mute_modal.hide_notifications": "隱藏來自這個使用者的通知?",
"navigation_bar.blocks": "封鎖的使用者",
"navigation_bar.community_timeline": "本地時間軸",
+ "navigation_bar.direct": "Direct messages",
"navigation_bar.domain_blocks": "隱藏的域名",
"navigation_bar.edit_profile": "編輯用者資訊",
"navigation_bar.favourites": "最愛",
@@ -238,6 +241,7 @@
"search_results.total": "{count, number} 項結果",
"standalone.public_title": "站點一瞥…",
"status.block": "封鎖 @{name}",
+ "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "此貼文無法轉推",
"status.delete": "刪除",
"status.direct": "Direct message @{name}",
@@ -253,6 +257,7 @@
"status.pin": "置頂到個人資訊頁",
"status.pinned": "置頂的推文",
"status.reblog": "轉推",
+ "status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} 轉推了",
"status.reply": "回應",
"status.replyAll": "回應這串",
diff --git a/app/javascript/mastodon/reducers/contexts.js b/app/javascript/mastodon/reducers/contexts.js
index c1ecf7e8a..ebd01e532 100644
--- a/app/javascript/mastodon/reducers/contexts.js
+++ b/app/javascript/mastodon/reducers/contexts.js
@@ -41,8 +41,9 @@ const deleteFromContexts = (immutableState, ids) => immutableState.withMutations
});
const filterContexts = (state, relationship, statuses) => {
- const ownedStatusIds = statuses.filter(status => status.get('account') === relationship.id)
- .map(status => status.get('id'));
+ const ownedStatusIds = statuses
+ .filter(status => status.get('account') === relationship.id)
+ .map(status => status.get('id'));
return deleteFromContexts(state, ownedStatusIds);
};
diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js
index 390b2a13a..9ec52a7fa 100644
--- a/app/javascript/mastodon/reducers/settings.js
+++ b/app/javascript/mastodon/reducers/settings.js
@@ -58,6 +58,12 @@ const initialState = ImmutableMap({
body: '',
}),
}),
+
+ direct: ImmutableMap({
+ regex: ImmutableMap({
+ body: '',
+ }),
+ }),
});
const defaultColumns = fromJS([
diff --git a/app/models/status.rb b/app/models/status.rb
index f924be47b..62857dd6b 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -183,6 +183,14 @@ class Status < ApplicationRecord
where(account: [account] + account.following).where(visibility: [:public, :unlisted, :private])
end
+ def as_direct_timeline(account)
+ query = joins("LEFT OUTER JOIN mentions ON statuses.id = mentions.status_id AND mentions.account_id = #{account.id}")
+ .where("mentions.account_id = #{account.id} OR statuses.account_id = #{account.id}")
+ .where(visibility: [:direct])
+
+ apply_timeline_filters(query, account, false)
+ end
+
def as_public_timeline(account = nil, local_only = false)
query = timeline_scope(local_only).without_replies
diff --git a/app/services/batched_remove_status_service.rb b/app/services/batched_remove_status_service.rb
index e2763c2b9..cb65a2256 100644
--- a/app/services/batched_remove_status_service.rb
+++ b/app/services/batched_remove_status_service.rb
@@ -36,6 +36,7 @@ class BatchedRemoveStatusService < BaseService
# Cannot be batched
statuses.each do |status|
unpush_from_public_timelines(status)
+ unpush_from_direct_timelines(status) if status.direct_visibility?
batch_salmon_slaps(status) if status.local?
end
@@ -87,6 +88,16 @@ class BatchedRemoveStatusService < BaseService
end
end
+ def unpush_from_direct_timelines(status)
+ payload = @json_payloads[status.id]
+ redis.pipelined do
+ @mentions[status.id].each do |mention|
+ redis.publish("timeline:direct:#{mention.account.id}", payload) if mention.account.local?
+ end
+ redis.publish("timeline:direct:#{status.account.id}", payload) if status.account.local?
+ end
+ end
+
def batch_salmon_slaps(status)
return if @mentions[status.id].empty?
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index bbaf3094b..0f77556dc 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -10,8 +10,11 @@ class FanOutOnWriteService < BaseService
deliver_to_self(status) if status.account.local?
+ render_anonymous_payload(status)
+
if status.direct_visibility?
deliver_to_mentioned_followers(status)
+ deliver_to_direct_timelines(status)
else
deliver_to_followers(status)
deliver_to_lists(status)
@@ -19,7 +22,6 @@ class FanOutOnWriteService < BaseService
return if status.account.silenced? || !status.public_visibility? || status.reblog?
- render_anonymous_payload(status)
deliver_to_hashtags(status)
return if status.reply? && status.in_reply_to_account_id != status.account_id
@@ -84,4 +86,13 @@ class FanOutOnWriteService < BaseService
Redis.current.publish('timeline:public', @payload)
Redis.current.publish('timeline:public:local', @payload) if status.local?
end
+
+ def deliver_to_direct_timelines(status)
+ Rails.logger.debug "Delivering status #{status.id} to direct timelines"
+
+ status.mentions.includes(:account).each do |mention|
+ Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local?
+ end
+ Redis.current.publish("timeline:direct:#{status.account.id}", @payload) if status.account.local?
+ end
end
diff --git a/app/services/remove_status_service.rb b/app/services/remove_status_service.rb
index a100f73ce..e164c03ab 100644
--- a/app/services/remove_status_service.rb
+++ b/app/services/remove_status_service.rb
@@ -20,6 +20,7 @@ class RemoveStatusService < BaseService
remove_reblogs
remove_from_hashtags
remove_from_public
+ remove_from_direct if status.direct_visibility?
@status.destroy!
@@ -130,6 +131,13 @@ class RemoveStatusService < BaseService
Redis.current.publish('timeline:public:local', @payload) if @status.local?
end
+ def remove_from_direct
+ @mentions.each do |mention|
+ Redis.current.publish("timeline:direct:#{mention.account.id}", @payload) if mention.account.local?
+ end
+ Redis.current.publish("timeline:direct:#{@account.id}", @payload) if @account.local?
+ end
+
def redis
Redis.current
end
diff --git a/config/routes.rb b/config/routes.rb
index 2776898ac..d959301e9 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -229,6 +229,7 @@ Rails.application.routes.draw do
end
namespace :timelines do
+ resource :direct, only: :show, controller: :direct
resource :home, only: :show, controller: :home
resource :public, only: :show, controller: :public
resources :tag, only: :show
diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb
index 4b5c20871..c6701018e 100644
--- a/spec/models/status_spec.rb
+++ b/spec/models/status_spec.rb
@@ -304,6 +304,55 @@ RSpec.describe Status, type: :model do
end
end
+ describe '.as_direct_timeline' do
+ let(:account) { Fabricate(:account) }
+ let(:followed) { Fabricate(:account) }
+ let(:not_followed) { Fabricate(:account) }
+
+ before do
+ Fabricate(:follow, account: account, target_account: followed)
+
+ @self_public_status = Fabricate(:status, account: account, visibility: :public)
+ @self_direct_status = Fabricate(:status, account: account, visibility: :direct)
+ @followed_public_status = Fabricate(:status, account: followed, visibility: :public)
+ @followed_direct_status = Fabricate(:status, account: followed, visibility: :direct)
+ @not_followed_direct_status = Fabricate(:status, account: not_followed, visibility: :direct)
+
+ @results = Status.as_direct_timeline(account)
+ end
+
+ it 'does not include public statuses from self' do
+ expect(@results).to_not include(@self_public_status)
+ end
+
+ it 'includes direct statuses from self' do
+ expect(@results).to include(@self_direct_status)
+ end
+
+ it 'does not include public statuses from followed' do
+ expect(@results).to_not include(@followed_public_status)
+ end
+
+ it 'includes direct statuses mentioning recipient from followed' do
+ Fabricate(:mention, account: account, status: @followed_direct_status)
+ expect(@results).to include(@followed_direct_status)
+ end
+
+ it 'does not include direct statuses not mentioning recipient from followed' do
+ expect(@results).to_not include(@followed_direct_status)
+ end
+
+ it 'includes direct statuses mentioning recipient from non-followed' do
+ Fabricate(:mention, account: account, status: @not_followed_direct_status)
+ expect(@results).to include(@not_followed_direct_status)
+ end
+
+ it 'does not include direct statuses not mentioning recipient from non-followed' do
+ expect(@results).to_not include(@not_followed_direct_status)
+ end
+
+ end
+
describe '.as_public_timeline' do
it 'only includes statuses with public visibility' do
public_status = Fabricate(:status, visibility: :public)
diff --git a/streaming/index.js b/streaming/index.js
index 1b4f8596c..48bab8078 100644
--- a/streaming/index.js
+++ b/streaming/index.js
@@ -466,6 +466,10 @@ const startWorker = (workerId) => {
streamFrom('timeline:public:local', req, streamToHttp(req, res), streamHttpEnd(req), true);
});
+ app.get('/api/v1/streaming/direct', (req, res) => {
+ streamFrom(`timeline:direct:${req.accountId}`, req, streamToHttp(req, res), streamHttpEnd(req), true);
+ });
+
app.get('/api/v1/streaming/hashtag', (req, res) => {
streamFrom(`timeline:hashtag:${req.query.tag.toLowerCase()}`, req, streamToHttp(req, res), streamHttpEnd(req), true);
});
@@ -517,6 +521,9 @@ const startWorker = (workerId) => {
case 'public:local':
streamFrom('timeline:public:local', req, streamToWs(req, ws), streamWsEnd(req, ws), true);
break;
+ case 'direct':
+ streamFrom(`timeline:direct:${req.accountId}`, req, streamToWs(req, ws), streamWsEnd(req, ws), true);
+ break;
case 'hashtag':
streamFrom(`timeline:hashtag:${location.query.tag.toLowerCase()}`, req, streamToWs(req, ws), streamWsEnd(req, ws), true);
break;
diff --git a/yarn.lock b/yarn.lock
index fba2cb9a7..c5a49a497 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5994,9 +5994,9 @@ rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-react-dom@^16.2.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.2.0.tgz#69003178601c0ca19b709b33a83369fe6124c044"
+react-dom@^16.3.0:
+ version "16.3.2"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.2.tgz#cb90f107e09536d683d84ed5d4888e9640e0e4df"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
@@ -6180,9 +6180,9 @@ react-transition-group@^2.2.0:
prop-types "^15.5.8"
warning "^3.0.0"
-react@^16.2.0:
- version "16.2.0"
- resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba"
+react@^16.3.0:
+ version "16.3.2"
+ resolved "https://registry.yarnpkg.com/react/-/react-16.3.2.tgz#fdc8420398533a1e58872f59091b272ce2f91ea9"
dependencies:
fbjs "^0.8.16"
loose-envify "^1.1.0"
From 7162a28c34868eb4b8cdd23a4078d99b46949491 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?=
Date: Wed, 18 Apr 2018 13:15:57 +0200
Subject: [PATCH 099/442] Add revealing/hiding statuses button to keyboard
shortcuts legend column (#7178)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marcin Mikołajczak
---
app/javascript/mastodon/features/keyboard_shortcuts/index.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.js b/app/javascript/mastodon/features/keyboard_shortcuts/index.js
index 8531e03c0..5ae7b34a2 100644
--- a/app/javascript/mastodon/features/keyboard_shortcuts/index.js
+++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.js
@@ -52,6 +52,10 @@ export default class KeyboardShortcuts extends ImmutablePureComponent {
title: "%{instance} Terms of Service and Privacy Policy"
themes:
+ contrast: High contrast
default: Mastodon
time:
formats:
diff --git a/config/themes.yml b/config/themes.yml
index a1049fae7..f0bb1e6f7 100644
--- a/config/themes.yml
+++ b/config/themes.yml
@@ -1 +1,2 @@
default: styles/application.scss
+contrast: styles/contrast.scss
From b8f0cfd6e34bc1285e952072a8c8a0eeafd8918c Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Sun, 22 Apr 2018 04:36:22 +0900
Subject: [PATCH 121/442] Add parallel test processors (#7215)
---
.circleci/config.yml | 7 ++-----
.env.test | 2 ++
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index e3a9628ac..c5d6ec9d1 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -6,13 +6,10 @@ aliases:
- image: circleci/ruby:2.5.1-stretch-node
environment: &ruby_environment
BUNDLE_APP_CONFIG: ./.bundle/
- RAILS_ENV: test
- NODE_ENV: test
DB_HOST: localhost
DB_USER: root
- LOCAL_DOMAIN: cb6e6126.ngrok.io
- LOCAL_HTTPS: true
- PARALLEL_TEST_PROCESSORS: 2
+ RAILS_ENV: test
+ PARALLEL_TEST_PROCESSORS: 4
ALLOW_NOPAM: true
working_directory: ~/projects/mastodon/
diff --git a/.env.test b/.env.test
index 7da76f8ef..726351c5e 100644
--- a/.env.test
+++ b/.env.test
@@ -1,3 +1,5 @@
+# Node.js
+NODE_ENV=test
# Federation
LOCAL_DOMAIN=cb6e6126.ngrok.io
LOCAL_HTTPS=true
From 9b8bb2a5df2839041ccd33e4ae7ec81b8746ddb2 Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Sun, 22 Apr 2018 04:56:40 +0900
Subject: [PATCH 122/442] Replace badge to CircleCI (#7216)
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 7b85b165b..34d56c96f 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
![Mastodon](https://i.imgur.com/NhZc40l.png)
========
-[![Build Status](https://img.shields.io/travis/tootsuite/mastodon.svg)][travis]
+[![Build Status](https://img.shields.io/circleci/project/github/tootsuite/mastodon.svg)][circleci]
[![Code Climate](https://img.shields.io/codeclimate/maintainability/tootsuite/mastodon.svg)][code_climate]
-[travis]: https://travis-ci.org/tootsuite/mastodon
+[circleci]: https://circleci.com/gh/tootsuite/mastodon
[code_climate]: https://codeclimate.com/github/tootsuite/mastodon
Mastodon is a **free, open-source social network server** based on **open web protocols** like ActivityPub and OStatus. The social focus of the project is a viable decentralized alternative to commercial social media silos that returns the control of the content distribution channels to the people. The technical focus of the project is a good user interface, a clean REST API for 3rd party apps and robust anti-abuse tools.
From 3f6893c6419c842f32dc0727db8d46dd8e457777 Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Sun, 22 Apr 2018 06:37:07 +0900
Subject: [PATCH 123/442] Reset locale on registration tests (#7219)
---
spec/controllers/auth/registrations_controller_spec.rb | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/spec/controllers/auth/registrations_controller_spec.rb b/spec/controllers/auth/registrations_controller_spec.rb
index 9cfbd481f..eeb01d5ad 100644
--- a/spec/controllers/auth/registrations_controller_spec.rb
+++ b/spec/controllers/auth/registrations_controller_spec.rb
@@ -73,6 +73,12 @@ RSpec.describe Auth::RegistrationsController, type: :controller do
describe 'POST #create' do
let(:accept_language) { Rails.application.config.i18n.available_locales.sample.to_s }
+ around do |example|
+ current_locale = I18n.locale
+ example.run
+ I18n.locale = current_locale
+ end
+
before { request.env["devise.mapping"] = Devise.mappings[:user] }
context do
From 3fa316147228819c48fd4f20c5c30f4f34b85f07 Mon Sep 17 00:00:00 2001
From: Matthias Beyer
Date: Sun, 22 Apr 2018 05:28:12 +0200
Subject: [PATCH 124/442] Fix: Use "welches" instead of "dass" in translation
(#7185)
---
config/locales/de.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 51936aa36..221437a08 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -428,7 +428,7 @@ de:
archive_takeout:
date: Datum
download: Dein Archiv herunterladen
- hint_html: Du kannst ein Archiv deiner Beiträge und hochgeladenen Medien anfragen. Die exportieren Daten werden im ActivityPub-Format gespeichert, dass lesbar mit jeder Software ist, die das Format unterstützt.
+ hint_html: Du kannst ein Archiv deiner Beiträge und hochgeladenen Medien anfragen. Die exportieren Daten werden im ActivityPub-Format gespeichert, welches mit jeder Software lesbar ist die das Format unterstützt.
in_progress: Stelle dein Archiv zusammen...
request: Dein Archiv anfragen
size: Größe
From 648d645c2fc4e7b266cb4d83bd4ed62e929dd363 Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Sun, 22 Apr 2018 18:41:39 +0900
Subject: [PATCH 125/442] Fix randomly fail (similar #7219) (#7225)
---
spec/controllers/concerns/localized_spec.rb | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/spec/controllers/concerns/localized_spec.rb b/spec/controllers/concerns/localized_spec.rb
index f71c96aff..8c80b7d2a 100644
--- a/spec/controllers/concerns/localized_spec.rb
+++ b/spec/controllers/concerns/localized_spec.rb
@@ -11,13 +11,17 @@ describe ApplicationController, type: :controller do
end
end
+ around do |example|
+ current_locale = I18n.locale
+ example.run
+ I18n.locale = current_locale
+ end
+
before do
routes.draw { get 'success' => 'anonymous#success' }
end
shared_examples 'default locale' do
- after { I18n.locale = I18n.default_locale }
-
it 'sets available and preferred language' do
request.headers['Accept-Language'] = 'ca-ES, fa'
get 'success'
From ca9192d9ba1c27689d7a14d0fb5b426c3d73c9f4 Mon Sep 17 00:00:00 2001
From: David Baucum
Date: Sun, 22 Apr 2018 05:49:16 -0400
Subject: [PATCH 126/442] Ability to specify Redis passwd on mastodon:setup
(#7222)
Closes #7221
---
lib/tasks/mastodon.rake | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index 505c7e0fa..b5a148337 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -107,9 +107,16 @@ namespace :mastodon do
q.convert :int
end
+ env['REDIS_PASSWORD'] = prompt.ask('Redis password:') do |q|
+ q.required false
+ a.default nil
+ q.modify :strip
+ end
+
redis_options = {
host: env['REDIS_HOST'],
port: env['REDIS_PORT'],
+ password: env['REDIS_PASSWORD'],
driver: :hiredis,
}
From 597948fb1316d2e1de76be330db441786c571132 Mon Sep 17 00:00:00 2001
From: ThibG
Date: Sun, 22 Apr 2018 12:10:37 +0200
Subject: [PATCH 127/442] Do not set emoji as inline-block (fixes #5743)
(#7207)
---
app/javascript/styles/mastodon/components.scss | 1 -
1 file changed, 1 deletion(-)
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index 1d0a7e945..f6e403b7d 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -556,7 +556,6 @@
}
.emojione {
- display: inline-block;
font-size: inherit;
vertical-align: middle;
object-fit: contain;
From 3c5006ec7fa98ec53df619b0e6e52b3bbdb6f046 Mon Sep 17 00:00:00 2001
From: Lynx Kotoura
Date: Sun, 22 Apr 2018 21:29:40 +0900
Subject: [PATCH 128/442] Fix text colors (#7227)
---
app/javascript/styles/contrast/variables.scss | 2 ++
app/javascript/styles/mastodon/components.scss | 6 +++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/app/javascript/styles/contrast/variables.scss b/app/javascript/styles/contrast/variables.scss
index 35d11060e..f6cadf029 100644
--- a/app/javascript/styles/contrast/variables.scss
+++ b/app/javascript/styles/contrast/variables.scss
@@ -4,6 +4,7 @@ $black: #000000;
$classic-base-color: #282c37;
$classic-primary-color: #9baec8;
$classic-secondary-color: #d9e1e8;
+$classic-highlight-color: #2b90d9;
$ui-base-color: $classic-base-color !default;
$ui-primary-color: $classic-primary-color !default;
@@ -15,6 +16,7 @@ $ui-highlight-color: #2b5fd9;
$darker-text-color: lighten($ui-primary-color, 20%) !default;
$dark-text-color: lighten($ui-primary-color, 12%) !default;
$secondary-text-color: lighten($ui-secondary-color, 6%) !default;
+$highlight-text-color: $classic-highlight-color !default;
$action-button-color: #8d9ac2;
$inverted-text-color: $black !default;
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index f6e403b7d..c84e61306 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -701,7 +701,7 @@
border-radius: 2px;
background: transparent;
border: 0;
- color: $lighter-text-color;
+ color: $inverted-text-color;
font-weight: 700;
font-size: 11px;
padding: 0 6px;
@@ -4037,6 +4037,10 @@ a.status-card {
overflow-y: auto;
overflow-x: hidden;
+ .status__content a {
+ color: $highlight-text-color;
+ }
+
@media screen and (max-width: 480px) {
max-height: 10vh;
}
From b305a2393378fb365f26f7b440a67be2d415c4e2 Mon Sep 17 00:00:00 2001
From: jumoru
Date: Sun, 22 Apr 2018 14:46:19 +0200
Subject: [PATCH 129/442] Fix: Use "exportierten" instead of "exportieren" in
translation (#7186)
Spotted when looking at https://metalhead.club/@thomas/99881521526619858
---
config/locales/de.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 221437a08..f4f842aef 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -428,7 +428,7 @@ de:
archive_takeout:
date: Datum
download: Dein Archiv herunterladen
- hint_html: Du kannst ein Archiv deiner Beiträge und hochgeladenen Medien anfragen. Die exportieren Daten werden im ActivityPub-Format gespeichert, welches mit jeder Software lesbar ist die das Format unterstützt.
+ hint_html: Du kannst ein Archiv deiner Beiträge und hochgeladenen Medien anfragen. Die exportierten Daten werden im ActivityPub-Format gespeichert, welches mit jeder Software lesbar ist die das Format unterstützt.
in_progress: Stelle dein Archiv zusammen...
request: Dein Archiv anfragen
size: Größe
From 4ca2f73b126de89a917680d60f40cae7f589f55f Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Sun, 22 Apr 2018 15:42:00 +0200
Subject: [PATCH 130/442] Rescue Mastodon::LengthValidationError in Remoteable
(#7228)
Fix #7198 by allowing records with optional attachments to save
---
app/models/concerns/remotable.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb
index 3b8c507c3..7f1ef5191 100644
--- a/app/models/concerns/remotable.rb
+++ b/app/models/concerns/remotable.rb
@@ -38,7 +38,7 @@ module Remotable
self[attribute_name] = url if has_attribute?(attribute_name)
end
- rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError => e
+ rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e
Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}"
nil
end
From 75c4ab9d12d3a2f3de52c51b5006fe9d5d9afae4 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Sun, 22 Apr 2018 22:09:03 +0200
Subject: [PATCH 131/442] Remove "nsfw" category for sensitive statuses in
OStatus serializer (#7048)
Fix #7011
---
app/lib/ostatus/atom_serializer.rb | 2 --
app/services/process_hashtags_service.rb | 2 --
spec/lib/ostatus/atom_serializer_spec.rb | 6 ------
3 files changed, 10 deletions(-)
diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb
index 055b4649c..7c66f2066 100644
--- a/app/lib/ostatus/atom_serializer.rb
+++ b/app/lib/ostatus/atom_serializer.rb
@@ -364,8 +364,6 @@ class OStatus::AtomSerializer
append_element(entry, 'category', nil, term: tag.name)
end
- append_element(entry, 'category', nil, term: 'nsfw') if status.sensitive?
-
status.media_attachments.each do |media|
append_element(entry, 'link', nil, rel: :enclosure, type: media.file_content_type, length: media.file_file_size, href: full_asset_url(media.file.url(:original, false)))
end
diff --git a/app/services/process_hashtags_service.rb b/app/services/process_hashtags_service.rb
index 990e01a4b..5b45c865f 100644
--- a/app/services/process_hashtags_service.rb
+++ b/app/services/process_hashtags_service.rb
@@ -7,7 +7,5 @@ class ProcessHashtagsService < BaseService
tags.map { |str| str.mb_chars.downcase }.uniq(&:to_s).each do |tag|
status.tags << Tag.where(name: tag).first_or_initialize(name: tag)
end
-
- status.update(sensitive: true) if tags.include?('nsfw')
end
end
diff --git a/spec/lib/ostatus/atom_serializer_spec.rb b/spec/lib/ostatus/atom_serializer_spec.rb
index 00e6f09dc..d46791307 100644
--- a/spec/lib/ostatus/atom_serializer_spec.rb
+++ b/spec/lib/ostatus/atom_serializer_spec.rb
@@ -386,12 +386,6 @@ RSpec.describe OStatus::AtomSerializer do
expect(entry.category[:term]).to eq 'tag'
end
- it 'appends category element for NSFW if status is sensitive' do
- status = Fabricate(:status, sensitive: true)
- entry = OStatus::AtomSerializer.new.entry(status.stream_entry)
- expect(entry.category[:term]).to eq 'nsfw'
- end
-
it 'appends link elements for media attachments' do
file = attachment_fixture('attachment.jpg')
media_attachment = Fabricate(:media_attachment, file: file)
From 05fb6f096db7c58698f8e0bc7fc79e129b241176 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Mon, 23 Apr 2018 00:43:36 +0200
Subject: [PATCH 132/442] Resize images before upload in web UI to reduce
bandwidth (#7223)
* Resize images before upload in web UI to reduce bandwidth
Fix #7218
* Fix issues
* Do not resize GIFs in JS
---
app/javascript/mastodon/actions/compose.js | 95 +++++++++++++++++++---
1 file changed, 85 insertions(+), 10 deletions(-)
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index eee9c6928..c8ea5aaba 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -174,6 +174,79 @@ export function submitComposeFail(error) {
};
};
+const MAX_IMAGE_DIMENSION = 1280;
+
+const dataURLtoBlob = dataURL => {
+ const BASE64_MARKER = ';base64,';
+
+ if (dataURL.indexOf(BASE64_MARKER) === -1) {
+ const parts = dataURL.split(',');
+ const contentType = parts[0].split(':')[1];
+ const raw = parts[1];
+
+ return new Blob([raw], { type: contentType });
+ }
+
+ const parts = dataURL.split(BASE64_MARKER);
+ const contentType = parts[0].split(':')[1];
+ const raw = window.atob(parts[1]);
+ const rawLength = raw.length;
+
+ const uInt8Array = new Uint8Array(rawLength);
+
+ for (let i = 0; i < rawLength; ++i) {
+ uInt8Array[i] = raw.charCodeAt(i);
+ }
+
+ return new Blob([uInt8Array], { type: contentType });
+};
+
+const resizeImage = (inputFile, callback) => {
+ if (inputFile.type.match(/image.*/) && inputFile.type !== 'image/gif') {
+ const reader = new FileReader();
+
+ reader.onload = e => {
+ const img = new Image();
+
+ img.onload = () => {
+ const canvas = document.createElement('canvas');
+ const { width, height } = img;
+
+ let newWidth, newHeight;
+
+ if (width < MAX_IMAGE_DIMENSION && height < MAX_IMAGE_DIMENSION) {
+ callback(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);
+
+ callback(dataURLtoBlob(canvas.toDataURL(inputFile.type)));
+ };
+
+ img.src = e.target.result;
+ };
+
+ reader.readAsDataURL(inputFile);
+ } else {
+ callback(inputFile);
+ }
+};
+
export function uploadCompose(files) {
return function (dispatch, getState) {
if (getState().getIn(['compose', 'media_attachments']).size > 3) {
@@ -182,17 +255,19 @@ export function uploadCompose(files) {
dispatch(uploadComposeRequest());
- let data = new FormData();
- data.append('file', files[0]);
+ resizeImage(files[0], file => {
+ let data = new FormData();
+ data.append('file', file);
- api(getState).post('/api/v1/media', data, {
- onUploadProgress: function (e) {
- dispatch(uploadComposeProgress(e.loaded, e.total));
- },
- }).then(function (response) {
- dispatch(uploadComposeSuccess(response.data));
- }).catch(function (error) {
- dispatch(uploadComposeFail(error));
+ api(getState).post('/api/v1/media', data, {
+ onUploadProgress: function (e) {
+ dispatch(uploadComposeProgress(e.loaded, e.total));
+ },
+ }).then(function (response) {
+ dispatch(uploadComposeSuccess(response.data));
+ }).catch(function (error) {
+ dispatch(uploadComposeFail(error));
+ });
});
};
};
From 660cb058e18f8607a0044b5a89614e1caeb07ed9 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Mon, 23 Apr 2018 00:43:53 +0200
Subject: [PATCH 133/442] Improve relative timestamps in web UI (#7233)
Use short instead of numeric month, display year when different year
E.g.: "Apr 4" instead of "4/4", "Apr 4, 2017" if different year
---
.../mastodon/components/relative_timestamp.js | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/app/javascript/mastodon/components/relative_timestamp.js b/app/javascript/mastodon/components/relative_timestamp.js
index 51588e78c..3c8db7092 100644
--- a/app/javascript/mastodon/components/relative_timestamp.js
+++ b/app/javascript/mastodon/components/relative_timestamp.js
@@ -20,7 +20,7 @@ const dateFormatOptions = {
};
const shortDateFormatOptions = {
- month: 'numeric',
+ month: 'short',
day: 'numeric',
};
@@ -66,12 +66,17 @@ export default class RelativeTimestamp extends React.Component {
static propTypes = {
intl: PropTypes.object.isRequired,
timestamp: PropTypes.string.isRequired,
+ year: PropTypes.number.isRequired,
};
state = {
now: this.props.intl.now(),
};
+ static defaultProps = {
+ year: (new Date()).getFullYear(),
+ };
+
shouldComponentUpdate (nextProps, nextState) {
// As of right now the locale doesn't change without a new page load,
// but we might as well check in case that ever changes.
@@ -114,7 +119,7 @@ export default class RelativeTimestamp extends React.Component {
}
render () {
- const { timestamp, intl } = this.props;
+ const { timestamp, intl, year } = this.props;
const date = new Date(timestamp);
const delta = this.state.now - date.getTime();
@@ -123,7 +128,7 @@ export default class RelativeTimestamp extends React.Component {
if (delta < 10 * SECOND) {
relativeTime = intl.formatMessage(messages.just_now);
- } else if (delta < 3 * DAY) {
+ } else if (delta < 7 * DAY) {
if (delta < MINUTE) {
relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) });
} else if (delta < HOUR) {
@@ -133,8 +138,10 @@ export default class RelativeTimestamp extends React.Component {
} else {
relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) });
}
- } else {
+ } else if (date.getFullYear() === year) {
relativeTime = intl.formatDate(date, shortDateFormatOptions);
+ } else {
+ relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' });
}
return (
From 0758b00bfddf4a2c845d0d611e50717a268fd48a Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Mon, 23 Apr 2018 16:15:51 +0900
Subject: [PATCH 134/442] Refactor resizeImage method (#7236)
- Use URL.createObjectURL (replace from FileReader)
- Use HTMLCanvasElement.prototype.toBlob
(replace from HTMLCanvasElement.prototype.toDataURL)
- Use Promise (replace callback interface)
---
app/javascript/mastodon/actions/compose.js | 92 ++-----------------
.../actions/push_notifications/registerer.js | 9 +-
app/javascript/mastodon/base_polyfills.js | 21 +++++
app/javascript/mastodon/load_polyfills.js | 7 +-
.../mastodon/utils/__tests__/base64-test.js | 10 ++
app/javascript/mastodon/utils/base64.js | 10 ++
app/javascript/mastodon/utils/resize_image.js | 66 +++++++++++++
7 files changed, 120 insertions(+), 95 deletions(-)
create mode 100644 app/javascript/mastodon/utils/__tests__/base64-test.js
create mode 100644 app/javascript/mastodon/utils/base64.js
create mode 100644 app/javascript/mastodon/utils/resize_image.js
diff --git a/app/javascript/mastodon/actions/compose.js b/app/javascript/mastodon/actions/compose.js
index c8ea5aaba..fe3e831d5 100644
--- a/app/javascript/mastodon/actions/compose.js
+++ b/app/javascript/mastodon/actions/compose.js
@@ -4,6 +4,7 @@ import { throttle } from 'lodash';
import { search as emojiSearch } from '../features/emoji/emoji_mart_search_light';
import { tagHistory } from '../settings';
import { useEmoji } from './emojis';
+import resizeImage from '../utils/resize_image';
import { importFetchedAccounts } from './importer';
import { updateTimeline } from './timelines';
import { showAlertForError } from './alerts';
@@ -174,79 +175,6 @@ export function submitComposeFail(error) {
};
};
-const MAX_IMAGE_DIMENSION = 1280;
-
-const dataURLtoBlob = dataURL => {
- const BASE64_MARKER = ';base64,';
-
- if (dataURL.indexOf(BASE64_MARKER) === -1) {
- const parts = dataURL.split(',');
- const contentType = parts[0].split(':')[1];
- const raw = parts[1];
-
- return new Blob([raw], { type: contentType });
- }
-
- const parts = dataURL.split(BASE64_MARKER);
- const contentType = parts[0].split(':')[1];
- const raw = window.atob(parts[1]);
- const rawLength = raw.length;
-
- const uInt8Array = new Uint8Array(rawLength);
-
- for (let i = 0; i < rawLength; ++i) {
- uInt8Array[i] = raw.charCodeAt(i);
- }
-
- return new Blob([uInt8Array], { type: contentType });
-};
-
-const resizeImage = (inputFile, callback) => {
- if (inputFile.type.match(/image.*/) && inputFile.type !== 'image/gif') {
- const reader = new FileReader();
-
- reader.onload = e => {
- const img = new Image();
-
- img.onload = () => {
- const canvas = document.createElement('canvas');
- const { width, height } = img;
-
- let newWidth, newHeight;
-
- if (width < MAX_IMAGE_DIMENSION && height < MAX_IMAGE_DIMENSION) {
- callback(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);
-
- callback(dataURLtoBlob(canvas.toDataURL(inputFile.type)));
- };
-
- img.src = e.target.result;
- };
-
- reader.readAsDataURL(inputFile);
- } else {
- callback(inputFile);
- }
-};
-
export function uploadCompose(files) {
return function (dispatch, getState) {
if (getState().getIn(['compose', 'media_attachments']).size > 3) {
@@ -255,20 +183,14 @@ export function uploadCompose(files) {
dispatch(uploadComposeRequest());
- resizeImage(files[0], file => {
- let data = new FormData();
+ resizeImage(files[0]).then(file => {
+ const data = new FormData();
data.append('file', file);
- api(getState).post('/api/v1/media', data, {
- onUploadProgress: function (e) {
- dispatch(uploadComposeProgress(e.loaded, e.total));
- },
- }).then(function (response) {
- dispatch(uploadComposeSuccess(response.data));
- }).catch(function (error) {
- dispatch(uploadComposeFail(error));
- });
- });
+ return api(getState).post('/api/v1/media', data, {
+ onUploadProgress: ({ loaded, total }) => dispatch(uploadComposeProgress(loaded, total)),
+ }).then(({ data }) => dispatch(uploadComposeSuccess(data)));
+ }).catch(error => dispatch(uploadComposeFail(error)));
};
};
diff --git a/app/javascript/mastodon/actions/push_notifications/registerer.js b/app/javascript/mastodon/actions/push_notifications/registerer.js
index 60b215f02..82fe4519a 100644
--- a/app/javascript/mastodon/actions/push_notifications/registerer.js
+++ b/app/javascript/mastodon/actions/push_notifications/registerer.js
@@ -1,4 +1,5 @@
import api from '../../api';
+import { decode as decodeBase64 } from '../../utils/base64';
import { pushNotificationsSetting } from '../../settings';
import { setBrowserSupport, setSubscription, clearSubscription } from './setter';
import { me } from '../../initial_state';
@@ -10,13 +11,7 @@ const urlBase64ToUint8Array = (base64String) => {
.replace(/\-/g, '+')
.replace(/_/g, '/');
- const rawData = window.atob(base64);
- const outputArray = new Uint8Array(rawData.length);
-
- for (let i = 0; i < rawData.length; ++i) {
- outputArray[i] = rawData.charCodeAt(i);
- }
- return outputArray;
+ return decodeBase64(base64);
};
const getApplicationServerKey = () => document.querySelector('[name="applicationServerKey"]').getAttribute('content');
diff --git a/app/javascript/mastodon/base_polyfills.js b/app/javascript/mastodon/base_polyfills.js
index 8fbb17785..997813a04 100644
--- a/app/javascript/mastodon/base_polyfills.js
+++ b/app/javascript/mastodon/base_polyfills.js
@@ -5,6 +5,7 @@ import includes from 'array-includes';
import assign from 'object-assign';
import values from 'object.values';
import isNaN from 'is-nan';
+import { decode as decodeBase64 } from './utils/base64';
if (!Array.prototype.includes) {
includes.shim();
@@ -21,3 +22,23 @@ if (!Object.values) {
if (!Number.isNaN) {
Number.isNaN = isNaN;
}
+
+if (!HTMLCanvasElement.prototype.toBlob) {
+ const BASE64_MARKER = ';base64,';
+
+ Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
+ value(callback, type = 'image/png', quality) {
+ const dataURL = this.toDataURL(type, quality);
+ let data;
+
+ if (dataURL.indexOf(BASE64_MARKER) >= 0) {
+ const [, base64] = dataURL.split(BASE64_MARKER);
+ data = decodeBase64(base64);
+ } else {
+ [, data] = dataURL.split(',');
+ }
+
+ callback(new Blob([data], { type }));
+ },
+ });
+}
diff --git a/app/javascript/mastodon/load_polyfills.js b/app/javascript/mastodon/load_polyfills.js
index 815e1905b..8cb81c1a6 100644
--- a/app/javascript/mastodon/load_polyfills.js
+++ b/app/javascript/mastodon/load_polyfills.js
@@ -12,12 +12,13 @@ function importExtraPolyfills() {
function loadPolyfills() {
const needsBasePolyfills = !(
+ Array.prototype.includes &&
+ HTMLCanvasElement.prototype.toBlob &&
window.Intl &&
+ Number.isNaN &&
Object.assign &&
Object.values &&
- Number.isNaN &&
- window.Symbol &&
- Array.prototype.includes
+ window.Symbol
);
// Latest version of Firefox and Safari do not have IntersectionObserver.
diff --git a/app/javascript/mastodon/utils/__tests__/base64-test.js b/app/javascript/mastodon/utils/__tests__/base64-test.js
new file mode 100644
index 000000000..1b3260faa
--- /dev/null
+++ b/app/javascript/mastodon/utils/__tests__/base64-test.js
@@ -0,0 +1,10 @@
+import * as base64 from '../base64';
+
+describe('base64', () => {
+ describe('decode', () => {
+ it('returns a uint8 array', () => {
+ const arr = base64.decode('dGVzdA==');
+ expect(arr).toEqual(new Uint8Array([116, 101, 115, 116]));
+ });
+ });
+});
diff --git a/app/javascript/mastodon/utils/base64.js b/app/javascript/mastodon/utils/base64.js
new file mode 100644
index 000000000..8226e2c54
--- /dev/null
+++ b/app/javascript/mastodon/utils/base64.js
@@ -0,0 +1,10 @@
+export const decode = base64 => {
+ const rawData = window.atob(base64);
+ const outputArray = new Uint8Array(rawData.length);
+
+ for (let i = 0; i < rawData.length; ++i) {
+ outputArray[i] = rawData.charCodeAt(i);
+ }
+
+ return outputArray;
+};
diff --git a/app/javascript/mastodon/utils/resize_image.js b/app/javascript/mastodon/utils/resize_image.js
new file mode 100644
index 000000000..6442eda38
--- /dev/null
+++ b/app/javascript/mastodon/utils/resize_image.js
@@ -0,0 +1,66 @@
+const MAX_IMAGE_DIMENSION = 1280;
+
+const getImageUrl = inputFile => new Promise((resolve, reject) => {
+ if (window.URL && URL.createObjectURL) {
+ try {
+ resolve(URL.createObjectURL(inputFile));
+ } catch (error) {
+ reject(error);
+ }
+ return;
+ }
+
+ const reader = new FileReader();
+ reader.onerror = (...args) => reject(...args);
+ reader.onload = ({ target }) => resolve(target.result);
+
+ reader.readAsDataURL(inputFile);
+});
+
+const loadImage = inputFile => new Promise((resolve, reject) => {
+ getImageUrl(inputFile).then(url => {
+ const img = new Image();
+
+ img.onerror = (...args) => reject(...args);
+ img.onload = () => resolve(img);
+
+ img.src = url;
+ }).catch(reject);
+});
+
+export default inputFile => new Promise((resolve, reject) => {
+ if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
+ resolve(inputFile);
+ return;
+ }
+
+ 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) {
+ 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);
+ }).catch(reject);
+});
From 3bf6da1ffcf8208a0608de7bff6e2155c40e2871 Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Mon, 23 Apr 2018 16:16:26 +0900
Subject: [PATCH 135/442] Move precompile step to build stage (#7235)
---
.circleci/config.yml | 55 ++++++++++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index c5d6ec9d1..fbaf60aad 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -23,6 +23,13 @@ aliases:
paths:
- ./mastodon/
+ - &restore_ruby_dependencies
+ restore_cache:
+ keys:
+ - v2-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
+ - v2-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-
+ - v2-ruby-dependencies--
+
- &install_steps
steps:
- checkout
@@ -54,26 +61,14 @@ aliases:
- *install_system_dependencies
- run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
- - restore_cache:
- keys:
- - v1-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
- - v1-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-
- - v1-ruby-dependencies--
+ - *restore_ruby_dependencies
- run: bundle install --clean --jobs 16 --path ./vendor/bundle/ --retry 3 --with pam_authentication --without development production
- save_cache:
- key: v1-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
+ key: v2-ruby-dependencies-{{ checksum "/tmp/.ruby-version" }}-{{ checksum "Gemfile.lock" }}
paths:
+ - ./.bundle/
- ./vendor/bundle/
- - run:
- name: Precompile Assets
- command: |
- if [ ! -d ./public/assets/ -o ! -d ./public/packs-test/ ]; then
- ./bin/rails assets:precompile
- fi
-
- - *persist_to_workspace
-
- &test_steps
steps:
- *attach_workspace
@@ -81,6 +76,15 @@ aliases:
- *install_system_dependencies
- run: sudo apt-get install -y ffmpeg
+ - run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
+ - *restore_ruby_dependencies
+
+ - restore_cache:
+ keys:
+ - precompiled-assets-{{ .Branch }}-{{ .Revision }}
+ - precompiled-assets-{{ .Branch }}-
+ - precompiled-assets--
+
- run:
name: Prepare Tests
command: ./bin/rails parallel:create parallel:load_schema parallel:prepare
@@ -104,6 +108,20 @@ jobs:
environment: *ruby_environment
<<: *install_ruby_dependencies
+ build:
+ <<: *defaults
+ steps:
+ - *attach_workspace
+ - *install_system_dependencies
+ - run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
+ - *restore_ruby_dependencies
+ - run: ./bin/rails assets:precompile
+ - save_cache:
+ key: precompiled-assets-{{ .Branch }}-{{ .Revision }}
+ paths:
+ - ./public/assets
+ - ./public/packs-test/
+
test-ruby2.5:
<<: *defaults
docker:
@@ -138,6 +156,8 @@ jobs:
<<: *defaults
steps:
- *attach_workspace
+ - run: ruby -e 'puts RUBY_VERSION' | tee /tmp/.ruby-version
+ - *restore_ruby_dependencies
- run: bundle exec i18n-tasks check-normalized
- run: bundle exec i18n-tasks unused
@@ -150,14 +170,19 @@ workflows:
requires:
- install
- install-ruby2.4:
+ requires:
+ - install
+ - build:
requires:
- install-ruby2.5
- test-ruby2.5:
requires:
- install-ruby2.5
+ - build
- test-ruby2.4:
requires:
- install-ruby2.4
+ - build
- test-webui:
requires:
- install
From 7db7d68136d8c58c6d354e85096137c39d421671 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Mon, 23 Apr 2018 09:16:38 +0200
Subject: [PATCH 136/442] Detect and prevent image bombs, max. processable
dimension 4096^2 (#7229)
---
app/lib/exceptions.rb | 1 +
app/models/concerns/attachmentable.rb | 32 ++++++++++++++++++++++++---
app/models/custom_emoji.rb | 2 ++
app/models/media_attachment.rb | 16 ++------------
4 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/app/lib/exceptions.rb b/app/lib/exceptions.rb
index e88e98eae..01346bfe5 100644
--- a/app/lib/exceptions.rb
+++ b/app/lib/exceptions.rb
@@ -6,6 +6,7 @@ module Mastodon
class ValidationError < Error; end
class HostValidationError < ValidationError; end
class LengthValidationError < ValidationError; end
+ class DimensionsValidationError < ValidationError; end
class RaceConditionError < Error; end
class UnexpectedResponseError < Error
diff --git a/app/models/concerns/attachmentable.rb b/app/models/concerns/attachmentable.rb
index 90ce88463..6f8489b89 100644
--- a/app/models/concerns/attachmentable.rb
+++ b/app/models/concerns/attachmentable.rb
@@ -1,10 +1,15 @@
# frozen_string_literal: true
+require 'mime/types'
+
module Attachmentable
extend ActiveSupport::Concern
+ MAX_MATRIX_LIMIT = 16_777_216 # 4096x4096px or approx. 16MB
+
included do
before_post_process :set_file_extensions
+ before_post_process :check_image_dimensions
end
private
@@ -12,10 +17,31 @@ module Attachmentable
def set_file_extensions
self.class.attachment_definitions.each_key do |attachment_name|
attachment = send(attachment_name)
+
next if attachment.blank?
- extension = Paperclip::Interpolations.content_type_extension(attachment, :original)
- basename = Paperclip::Interpolations.basename(attachment, :original)
- attachment.instance_write :file_name, [basename, extension].delete_if(&:blank?).join('.')
+
+ attachment.instance_write :file_name, [Paperclip::Interpolations.basename(attachment, :original), appropriate_extension(attachment)].delete_if(&:blank?).join('.')
end
end
+
+ def check_image_dimensions
+ self.class.attachment_definitions.each_key do |attachment_name|
+ attachment = send(attachment_name)
+
+ next if attachment.blank? || !attachment.content_type.match?(/image.*/) || attachment.queued_for_write[:original].blank?
+
+ width, height = FastImage.size(attachment.queued_for_write[:original].path)
+
+ raise Mastodon::DimensionsValidationError, "#{width}x#{height} images are not supported" if width.present? && height.present? && (width * height >= MAX_MATRIX_LIMIT)
+ end
+ end
+
+ def appropriate_extension(attachment)
+ mime_type = MIME::Types[attachment.content_type]
+
+ extensions_for_mime_type = mime_type.empty? ? [] : mime_type.first.extensions
+ original_extension = Paperclip::Interpolations.extension(attachment, :original)
+
+ extensions_for_mime_type.include?(original_extension) ? original_extension : extensions_for_mime_type.first
+ end
end
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 1ec21d1a0..2dd3cac61 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -40,6 +40,8 @@ class CustomEmoji < ApplicationRecord
remotable_attachment :image, LIMIT
+ include Attachmentable
+
def local?
domain.nil?
end
diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index 8fd9ac09f..c9abab9e2 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -19,8 +19,6 @@
# description :text
#
-require 'mime/types'
-
class MediaAttachment < ApplicationRecord
self.inheritance_column = nil
@@ -70,6 +68,8 @@ class MediaAttachment < ApplicationRecord
validates_attachment_size :file, less_than: LIMIT
remotable_attachment :file, LIMIT
+ include Attachmentable
+
validates :account, presence: true
validates :description, length: { maximum: 420 }, if: :local?
@@ -176,9 +176,6 @@ class MediaAttachment < ApplicationRecord
def set_type_and_extension
self.type = VIDEO_MIME_TYPES.include?(file_content_type) ? :video : :image
- extension = appropriate_extension
- basename = Paperclip::Interpolations.basename(file, :original)
- file.instance_write :file_name, [basename, extension].delete_if(&:blank?).join('.')
end
def set_meta
@@ -223,13 +220,4 @@ class MediaAttachment < ApplicationRecord
bitrate: movie.bitrate,
}
end
-
- def appropriate_extension
- mime_type = MIME::Types[file.content_type]
-
- extensions_for_mime_type = mime_type.empty? ? [] : mime_type.first.extensions
- original_extension = Paperclip::Interpolations.extension(file, :original)
-
- extensions_for_mime_type.include?(original_extension) ? original_extension : extensions_for_mime_type.first
- end
end
From 9613a53cb36a2d4cb1dd1c9a1eced0f61b7970dc Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Mon, 23 Apr 2018 18:29:17 +0900
Subject: [PATCH 137/442] Update dependencies for Ruby (2018-04-23) (#7237)
* Update annotate to version 2.7.3
* Update aws-sdk-s3 to version 1.9.2
* Update browser to version 2.5.3
* Update capistrano to version 3.10.2
* Update domain_name to version 0.5.20180417
* Update http to version 3.2.0
* Update lograge to version 0.10.0
* Update oj to version 3.5.1
* Update parallel_tests to version 2.21.3
* Update puma to version 3.11.4
* Update rubocop to version 0.55.0
* Update scss_lint to version 0.57.0
* Update simplecov to version 0.16.1
* Update tty-command to version 0.8.0
* Update tty-prompt to version 0.16.0
* Update pkg-config to version 1.3.0
* Update fog-local to version 0.5.0
* Update fog-openstack to version 0.1.25
* Update devise-two-factor to version 3.0.3
* bundle update
---
Gemfile | 28 +++---
Gemfile.lock | 136 ++++++++++++--------------
app/models/account.rb | 4 +-
app/models/account_domain_block.rb | 4 +-
app/models/account_moderation_note.rb | 6 +-
app/models/admin/action_log.rb | 6 +-
app/models/backup.rb | 4 +-
app/models/block.rb | 6 +-
app/models/conversation.rb | 2 +-
app/models/conversation_mute.rb | 6 +-
app/models/custom_emoji.rb | 2 +-
app/models/domain_block.rb | 2 +-
app/models/email_domain_block.rb | 2 +-
app/models/favourite.rb | 6 +-
app/models/follow.rb | 6 +-
app/models/follow_request.rb | 6 +-
app/models/import.rb | 4 +-
app/models/invite.rb | 4 +-
app/models/list.rb | 4 +-
app/models/list_account.rb | 8 +-
app/models/media_attachment.rb | 6 +-
app/models/mention.rb | 6 +-
app/models/mute.rb | 6 +-
app/models/notification.rb | 8 +-
app/models/preview_card.rb | 2 +-
app/models/report.rb | 12 +--
app/models/report_note.rb | 6 +-
app/models/session_activation.rb | 8 +-
app/models/setting.rb | 4 +-
app/models/site_upload.rb | 2 +-
app/models/status.rb | 14 +--
app/models/status_pin.rb | 6 +-
app/models/stream_entry.rb | 6 +-
app/models/subscription.rb | 4 +-
app/models/tag.rb | 2 +-
app/models/user.rb | 6 +-
app/models/web/push_subscription.rb | 2 +-
app/models/web/setting.rb | 4 +-
config/deploy.rb | 2 +-
39 files changed, 173 insertions(+), 179 deletions(-)
diff --git a/Gemfile b/Gemfile
index 8055f1561..a33748568 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,7 +3,7 @@
source 'https://rubygems.org'
ruby '>= 2.3.0', '< 2.6.0'
-gem 'pkg-config', '~> 1.2'
+gem 'pkg-config', '~> 1.3'
gem 'puma', '~> 3.11'
gem 'rails', '~> 5.2.0'
@@ -11,11 +11,11 @@ gem 'rails', '~> 5.2.0'
gem 'hamlit-rails', '~> 0.2'
gem 'pg', '~> 1.0'
gem 'pghero', '~> 2.1'
-gem 'dotenv-rails', '~> 2.2'
+gem 'dotenv-rails', '~> 2.2', '< 2.3'
-gem 'aws-sdk-s3', '~> 1.8', require: false
+gem 'aws-sdk-s3', '~> 1.9', require: false
gem 'fog-core', '~> 1.45'
-gem 'fog-local', '~> 0.4', require: false
+gem 'fog-local', '~> 0.5', require: false
gem 'fog-openstack', '~> 0.1', require: false
gem 'paperclip', '~> 6.0'
gem 'paperclip-av-transcoder', '~> 0.6'
@@ -30,7 +30,7 @@ gem 'iso-639'
gem 'chewy', '~> 5.0'
gem 'cld3', '~> 3.2.0'
gem 'devise', '~> 4.4'
-gem 'devise-two-factor', '~> 3.0', git: 'https://github.com/ykzts/devise-two-factor.git', branch: 'rails-5.2'
+gem 'devise-two-factor', '~> 3.0'
group :pam_authentication, optional: true do
gem 'devise_pam_authenticatable2', '~> 9.1'
@@ -48,7 +48,7 @@ gem 'goldfinger', '~> 2.1'
gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.5'
gem 'htmlentities', '~> 4.3'
-gem 'http', '~> 3.0'
+gem 'http', '~> 3.2'
gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 1.0'
gem 'idn-ruby', require: 'idn'
@@ -57,9 +57,9 @@ gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.1'
gem 'nokogiri', '~> 1.8'
gem 'nsa', '~> 0.2'
-gem 'oj', '~> 3.4'
+gem 'oj', '~> 3.5'
gem 'ostatus2', '~> 2.0'
-gem 'ox', '~> 2.8'
+gem 'ox', '~> 2.9'
gem 'pundit', '~> 1.1'
gem 'premailer-rails'
gem 'rack-attack', '~> 5.2'
@@ -82,8 +82,8 @@ gem 'simple_form', '~> 4.0'
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
gem 'stoplight', '~> 2.1.3'
gem 'strong_migrations', '~> 0.2'
-gem 'tty-command'
-gem 'tty-prompt'
+gem 'tty-command', '~> 0.8'
+gem 'tty-prompt', '~> 0.16'
gem 'twitter-text', '~> 1.14'
gem 'tzinfo-data', '~> 1.2018'
gem 'webpacker', '~> 3.4'
@@ -112,7 +112,7 @@ group :test do
gem 'rails-controller-testing', '~> 1.0'
gem 'rspec-sidekiq', '~> 3.0'
gem 'rspec-retry', '~> 0.5', require: false
- gem 'simplecov', '~> 0.14', require: false
+ gem 'simplecov', '~> 0.16', require: false
gem 'webmock', '~> 3.3'
gem 'parallel_tests', '~> 2.21'
end
@@ -126,10 +126,10 @@ group :development do
gem 'letter_opener', '~> 1.4'
gem 'letter_opener_web', '~> 1.3'
gem 'memory_profiler'
- gem 'rubocop', require: false
+ gem 'rubocop', '~> 0.55', require: false
gem 'brakeman', '~> 4.2', require: false
gem 'bundler-audit', '~> 0.6', require: false
- gem 'scss_lint', '~> 0.55', require: false
+ gem 'scss_lint', '~> 0.57', require: false
gem 'capistrano', '~> 3.10'
gem 'capistrano-rails', '~> 1.3'
@@ -138,6 +138,6 @@ group :development do
end
group :production do
- gem 'lograge', '~> 0.9'
+ gem 'lograge', '~> 0.10'
gem 'redis-rails', '~> 5.0'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index eeb4bf17e..d96165dcf 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,15 +1,3 @@
-GIT
- remote: https://github.com/ykzts/devise-two-factor.git
- revision: f60492b29c174d4c959ac02406392f8eb9c4d374
- branch: rails-5.2
- specs:
- devise-two-factor (3.0.2)
- activesupport (< 5.3)
- attr_encrypted (>= 1.3, < 4, != 2)
- devise (~> 4.0)
- railties (< 5.3)
- rotp (~> 2.0)
-
GEM
remote: https://rubygems.org/
specs:
@@ -64,7 +52,7 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
airbrussh (1.3.0)
sshkit (>= 1.6.1, != 1.7.0)
- annotate (2.7.2)
+ annotate (2.7.3)
activerecord (>= 3.2, < 6.0)
rake (>= 10.4, < 13.0)
arel (9.0.0)
@@ -73,15 +61,15 @@ GEM
encryptor (~> 3.0.0)
av (0.9.0)
cocaine (~> 0.5.3)
- aws-partitions (1.70.0)
- aws-sdk-core (3.17.0)
+ aws-partitions (1.80.0)
+ aws-sdk-core (3.19.0)
aws-partitions (~> 1.0)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
aws-sdk-kms (1.5.0)
aws-sdk-core (~> 3)
aws-sigv4 (~> 1.0)
- aws-sdk-s3 (1.8.2)
+ aws-sdk-s3 (1.9.1)
aws-sdk-core (~> 3)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.0)
@@ -96,7 +84,7 @@ GEM
bootsnap (1.3.0)
msgpack (~> 1.0)
brakeman (4.2.1)
- browser (2.5.2)
+ browser (2.5.3)
builder (3.2.3)
bullet (5.7.5)
activesupport (>= 3.0.0)
@@ -104,7 +92,7 @@ GEM
bundler-audit (0.6.0)
bundler (~> 1.2)
thor (~> 0.18)
- capistrano (3.10.1)
+ capistrano (3.10.2)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
@@ -156,12 +144,18 @@ GEM
railties (>= 4.1.0, < 6.0)
responders
warden (~> 1.2.3)
+ devise-two-factor (3.0.3)
+ activesupport (< 5.3)
+ attr_encrypted (>= 1.3, < 4, != 2)
+ devise (~> 4.0)
+ railties (< 5.3)
+ rotp (~> 2.0)
devise_pam_authenticatable2 (9.1.0)
devise (>= 4.0.0)
rpam2 (~> 4.0)
diff-lcs (1.3)
- docile (1.1.5)
- domain_name (0.5.20170404)
+ docile (1.3.0)
+ domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.3.2)
railties (>= 4.2)
@@ -172,29 +166,29 @@ GEM
easy_translate (0.5.1)
thread
thread_safe
- elasticsearch (6.0.1)
- elasticsearch-api (= 6.0.1)
- elasticsearch-transport (= 6.0.1)
- elasticsearch-api (6.0.1)
+ elasticsearch (6.0.2)
+ elasticsearch-api (= 6.0.2)
+ elasticsearch-transport (= 6.0.2)
+ elasticsearch-api (6.0.2)
multi_json
elasticsearch-dsl (0.1.5)
- elasticsearch-transport (6.0.1)
+ elasticsearch-transport (6.0.2)
faraday
multi_json
encryptor (3.0.0)
equatable (0.5.0)
erubi (1.7.1)
- et-orbi (1.0.9)
+ et-orbi (1.1.0)
tzinfo
- excon (0.60.0)
+ excon (0.62.0)
fabrication (2.20.1)
faker (1.8.7)
i18n (>= 0.7)
- faraday (0.14.0)
+ faraday (0.15.0)
multipart-post (>= 1.2, < 3)
fast_blank (1.0.0)
fastimage (2.1.1)
- ffi (1.9.21)
+ ffi (1.9.23)
fog-core (1.45.0)
builder
excon (~> 0.58)
@@ -202,9 +196,9 @@ GEM
fog-json (1.0.2)
fog-core (~> 1.0)
multi_json (~> 1.10)
- fog-local (0.4.0)
- fog-core (~> 1.27)
- fog-openstack (0.1.23)
+ fog-local (0.5.0)
+ fog-core (>= 1.27, < 3.0)
+ fog-openstack (0.1.25)
fog-core (~> 1.40)
fog-json (>= 1.0)
ipaddress (>= 0.8)
@@ -237,20 +231,20 @@ GEM
hitimes (1.2.6)
hkdf (0.3.0)
htmlentities (4.3.4)
- http (3.0.0)
+ http (3.2.0)
addressable (~> 2.3)
http-cookie (~> 1.0)
- http-form_data (>= 2.0.0.pre.pre2, < 3)
+ http-form_data (~> 2.0)
http_parser.rb (~> 0.6.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
- http-form_data (2.0.0)
+ http-form_data (2.1.0)
http_accept_language (2.1.1)
http_parser.rb (0.6.0)
httplog (1.0.2)
colorize (~> 0.8)
rack (>= 1.0)
- i18n (1.0.0)
+ i18n (1.0.1)
concurrent-ruby (~> 1.0)
i18n-tasks (0.9.21)
activesupport (>= 4.0.2)
@@ -265,7 +259,7 @@ GEM
idn-ruby (0.1.0)
ipaddress (0.8.3)
iso-639 (0.2.8)
- jmespath (1.3.1)
+ jmespath (1.4.0)
json (2.1.0)
json-ld (2.2.1)
multi_json (~> 1.12)
@@ -297,7 +291,7 @@ GEM
letter_opener (~> 1.0)
railties (>= 3.2)
link_header (0.0.8)
- lograge (0.9.0)
+ lograge (0.10.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
@@ -341,7 +335,7 @@ GEM
concurrent-ruby (~> 1.0.0)
sidekiq (>= 3.5.0)
statsd-ruby (~> 1.2.0)
- oj (3.4.0)
+ oj (3.5.1)
omniauth (1.8.1)
hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3)
@@ -357,7 +351,7 @@ GEM
addressable (~> 2.5)
http (~> 3.0)
nokogiri (~> 1.8)
- ox (2.8.2)
+ ox (2.9.2)
paperclip (6.0.0)
activemodel (>= 4.2.0)
activesupport (>= 4.2.0)
@@ -368,7 +362,7 @@ GEM
av (~> 0.9.0)
paperclip (>= 2.5.2)
parallel (1.12.1)
- parallel_tests (2.21.1)
+ parallel_tests (2.21.3)
parallel
parser (2.5.1.0)
ast (~> 2.4.0)
@@ -378,7 +372,7 @@ GEM
pg (1.0.0)
pghero (2.1.0)
activerecord
- pkg-config (1.2.9)
+ pkg-config (1.3.0)
powerpack (0.1.1)
premailer (1.11.1)
addressable
@@ -394,7 +388,7 @@ GEM
pry-rails (0.3.6)
pry (>= 0.10.4)
public_suffix (3.0.2)
- puma (3.11.3)
+ puma (3.11.4)
pundit (1.1.0)
activesupport (>= 3.0.0)
rack (2.0.4)
@@ -443,10 +437,10 @@ GEM
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
rake (12.3.1)
- rb-fsevent (0.10.2)
+ rb-fsevent (0.10.3)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
- rdf (3.0.1)
+ rdf (3.0.2)
hamster (~> 3.0)
link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.3.3)
@@ -468,9 +462,9 @@ GEM
redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2)
- redis-store (1.4.1)
+ redis-store (1.5.0)
redis (>= 2.2, < 5)
- request_store (1.4.0)
+ request_store (1.4.1)
rack (>= 1.4)
responders (2.4.0)
actionpack (>= 4.2.0, < 5.3)
@@ -501,9 +495,9 @@ GEM
rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0)
rspec-support (3.7.1)
- rubocop (0.52.1)
+ rubocop (0.55.0)
parallel (~> 1.10)
- parser (>= 2.4.0.2, < 3.0)
+ parser (>= 2.5)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
@@ -519,14 +513,14 @@ GEM
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
nokogumbo (~> 1.4)
- sass (3.5.5)
+ sass (3.5.6)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
- scss_lint (0.56.0)
+ scss_lint (0.57.0)
rake (>= 0.9, < 13)
- sass (~> 3.5.3)
+ sass (~> 3.5.5)
sidekiq (5.1.3)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
@@ -548,8 +542,8 @@ GEM
simple_form (4.0.0)
actionpack (> 4)
activemodel (> 4)
- simplecov (0.15.1)
- docile (~> 1.1.0)
+ simplecov (0.16.1)
+ docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
@@ -581,10 +575,10 @@ GEM
timers (4.1.2)
hitimes
tty-color (0.4.2)
- tty-command (0.7.0)
+ tty-command (0.8.0)
pastel (~> 0.7.0)
tty-cursor (0.5.0)
- tty-prompt (0.15.0)
+ tty-prompt (0.16.0)
necromancer (~> 0.4.0)
pastel (~> 0.7.0)
timers (~> 4.0)
@@ -604,7 +598,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
- unicode-display_width (1.3.0)
+ unicode-display_width (1.3.2)
uniform_notifier (1.11.0)
warden (1.2.7)
rack (>= 1.0)
@@ -634,7 +628,7 @@ DEPENDENCIES
active_record_query_trace (~> 1.5)
addressable (~> 2.5)
annotate (~> 2.7)
- aws-sdk-s3 (~> 1.8)
+ aws-sdk-s3 (~> 1.9)
better_errors (~> 2.4)
binding_of_caller (~> 0.7)
bootsnap (~> 1.3)
@@ -652,23 +646,23 @@ DEPENDENCIES
cld3 (~> 3.2.0)
climate_control (~> 0.2)
devise (~> 4.4)
- devise-two-factor (~> 3.0)!
+ devise-two-factor (~> 3.0)
devise_pam_authenticatable2 (~> 9.1)
doorkeeper (~> 4.3)
- dotenv-rails (~> 2.2)
+ dotenv-rails (~> 2.2, < 2.3)
fabrication (~> 2.20)
faker (~> 1.8)
fast_blank (~> 1.0)
fastimage
fog-core (~> 1.45)
- fog-local (~> 0.4)
+ fog-local (~> 0.5)
fog-openstack (~> 0.1)
fuubar (~> 2.2)
goldfinger (~> 2.1)
hamlit-rails (~> 0.2)
hiredis (~> 0.6)
htmlentities (~> 4.3)
- http (~> 3.0)
+ http (~> 3.2)
http_accept_language (~> 2.1)
httplog (~> 1.0)
i18n-tasks (~> 0.9)
@@ -679,7 +673,7 @@ DEPENDENCIES
letter_opener (~> 1.4)
letter_opener_web (~> 1.3)
link_header (~> 0.0)
- lograge (~> 0.9)
+ lograge (~> 0.10)
mario-redis-lock (~> 1.2)
memory_profiler
microformats (~> 4.0)
@@ -687,18 +681,18 @@ DEPENDENCIES
net-ldap (~> 0.10)
nokogiri (~> 1.8)
nsa (~> 0.2)
- oj (~> 3.4)
+ oj (~> 3.5)
omniauth (~> 1.2)
omniauth-cas (~> 1.1)
omniauth-saml (~> 1.10)
ostatus2 (~> 2.0)
- ox (~> 2.8)
+ ox (~> 2.9)
paperclip (~> 6.0)
paperclip-av-transcoder (~> 0.6)
parallel_tests (~> 2.21)
pg (~> 1.0)
pghero (~> 2.1)
- pkg-config (~> 1.2)
+ pkg-config (~> 1.3)
premailer-rails
private_address_check (~> 0.4.1)
pry-rails (~> 0.3)
@@ -719,24 +713,24 @@ DEPENDENCIES
rspec-rails (~> 3.7)
rspec-retry (~> 0.5)
rspec-sidekiq (~> 3.0)
- rubocop
+ rubocop (~> 0.55)
ruby-oembed (~> 0.12)
ruby-progressbar (~> 1.4)
sanitize (~> 4.6)
- scss_lint (~> 0.55)
+ scss_lint (~> 0.57)
sidekiq (~> 5.1)
sidekiq-bulk (~> 0.1.1)
sidekiq-scheduler (~> 2.2)
sidekiq-unique-jobs (~> 5.0)
simple-navigation (~> 4.0)
simple_form (~> 4.0)
- simplecov (~> 0.14)
+ simplecov (~> 0.16)
sprockets-rails (~> 3.2)
stoplight (~> 2.1.3)
streamio-ffmpeg (~> 3.0)
strong_migrations (~> 0.2)
- tty-command
- tty-prompt
+ tty-command (~> 0.8)
+ tty-prompt (~> 0.16)
twitter-text (~> 1.14)
tzinfo-data (~> 1.2018)
webmock (~> 3.3)
diff --git a/app/models/account.rb b/app/models/account.rb
index a3436b47c..0a4370be4 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -3,7 +3,7 @@
#
# Table name: accounts
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# username :string default(""), not null
# domain :string
# secret :string default(""), not null
@@ -42,7 +42,7 @@
# followers_url :string default(""), not null
# protocol :integer default("ostatus"), not null
# memorial :boolean default(FALSE), not null
-# moved_to_account_id :integer
+# moved_to_account_id :bigint(8)
# featured_collection_url :string
# fields :jsonb
#
diff --git a/app/models/account_domain_block.rb b/app/models/account_domain_block.rb
index bc00b4f32..e352000c3 100644
--- a/app/models/account_domain_block.rb
+++ b/app/models/account_domain_block.rb
@@ -3,11 +3,11 @@
#
# Table name: account_domain_blocks
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# domain :string
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer
+# account_id :bigint(8)
#
class AccountDomainBlock < ApplicationRecord
diff --git a/app/models/account_moderation_note.rb b/app/models/account_moderation_note.rb
index 3ac9b1ac1..22e312bb2 100644
--- a/app/models/account_moderation_note.rb
+++ b/app/models/account_moderation_note.rb
@@ -3,10 +3,10 @@
#
# Table name: account_moderation_notes
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# content :text not null
-# account_id :integer not null
-# target_account_id :integer not null
+# account_id :bigint(8) not null
+# target_account_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
#
diff --git a/app/models/admin/action_log.rb b/app/models/admin/action_log.rb
index 81f278e07..1d1db1b7a 100644
--- a/app/models/admin/action_log.rb
+++ b/app/models/admin/action_log.rb
@@ -3,11 +3,11 @@
#
# Table name: admin_action_logs
#
-# id :integer not null, primary key
-# account_id :integer
+# id :bigint(8) not null, primary key
+# account_id :bigint(8)
# action :string default(""), not null
# target_type :string
-# target_id :integer
+# target_id :bigint(8)
# recorded_changes :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
diff --git a/app/models/backup.rb b/app/models/backup.rb
index 5a7e6a14d..c2651313b 100644
--- a/app/models/backup.rb
+++ b/app/models/backup.rb
@@ -3,8 +3,8 @@
#
# Table name: backups
#
-# id :integer not null, primary key
-# user_id :integer
+# id :bigint(8) not null, primary key
+# user_id :bigint(8)
# dump_file_name :string
# dump_content_type :string
# dump_file_size :integer
diff --git a/app/models/block.rb b/app/models/block.rb
index d6ecabd3b..df4a6bbac 100644
--- a/app/models/block.rb
+++ b/app/models/block.rb
@@ -3,11 +3,11 @@
#
# Table name: blocks
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# target_account_id :integer not null
+# account_id :bigint(8) not null
+# target_account_id :bigint(8) not null
#
class Block < ApplicationRecord
diff --git a/app/models/conversation.rb b/app/models/conversation.rb
index 08c1ce945..4dfaea889 100644
--- a/app/models/conversation.rb
+++ b/app/models/conversation.rb
@@ -3,7 +3,7 @@
#
# Table name: conversations
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# uri :string
# created_at :datetime not null
# updated_at :datetime not null
diff --git a/app/models/conversation_mute.rb b/app/models/conversation_mute.rb
index 272eb81af..52c1a33e0 100644
--- a/app/models/conversation_mute.rb
+++ b/app/models/conversation_mute.rb
@@ -3,9 +3,9 @@
#
# Table name: conversation_mutes
#
-# id :integer not null, primary key
-# conversation_id :integer not null
-# account_id :integer not null
+# id :bigint(8) not null, primary key
+# conversation_id :bigint(8) not null
+# account_id :bigint(8) not null
#
class ConversationMute < ApplicationRecord
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
index 2dd3cac61..8235332f1 100644
--- a/app/models/custom_emoji.rb
+++ b/app/models/custom_emoji.rb
@@ -3,7 +3,7 @@
#
# Table name: custom_emojis
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# shortcode :string default(""), not null
# domain :string
# image_file_name :string
diff --git a/app/models/domain_block.rb b/app/models/domain_block.rb
index aea8919af..93658793b 100644
--- a/app/models/domain_block.rb
+++ b/app/models/domain_block.rb
@@ -3,7 +3,7 @@
#
# Table name: domain_blocks
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# domain :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb
index a104810d1..10490375b 100644
--- a/app/models/email_domain_block.rb
+++ b/app/models/email_domain_block.rb
@@ -3,7 +3,7 @@
#
# Table name: email_domain_blocks
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# domain :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
diff --git a/app/models/favourite.rb b/app/models/favourite.rb
index fa1884b86..c998a67eb 100644
--- a/app/models/favourite.rb
+++ b/app/models/favourite.rb
@@ -3,11 +3,11 @@
#
# Table name: favourites
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# status_id :integer not null
+# account_id :bigint(8) not null
+# status_id :bigint(8) not null
#
class Favourite < ApplicationRecord
diff --git a/app/models/follow.rb b/app/models/follow.rb
index 8e6fe537a..2ca42ff70 100644
--- a/app/models/follow.rb
+++ b/app/models/follow.rb
@@ -3,11 +3,11 @@
#
# Table name: follows
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# target_account_id :integer not null
+# account_id :bigint(8) not null
+# target_account_id :bigint(8) not null
# show_reblogs :boolean default(TRUE), not null
#
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
index cde26ceed..d559a8f62 100644
--- a/app/models/follow_request.rb
+++ b/app/models/follow_request.rb
@@ -3,11 +3,11 @@
#
# Table name: follow_requests
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# target_account_id :integer not null
+# account_id :bigint(8) not null
+# target_account_id :bigint(8) not null
# show_reblogs :boolean default(TRUE), not null
#
diff --git a/app/models/import.rb b/app/models/import.rb
index fdb4c6b80..55e970b0d 100644
--- a/app/models/import.rb
+++ b/app/models/import.rb
@@ -3,7 +3,7 @@
#
# Table name: imports
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# type :integer not null
# approved :boolean default(FALSE), not null
# created_at :datetime not null
@@ -12,7 +12,7 @@
# data_content_type :string
# data_file_size :integer
# data_updated_at :datetime
-# account_id :integer not null
+# account_id :bigint(8) not null
#
class Import < ApplicationRecord
diff --git a/app/models/invite.rb b/app/models/invite.rb
index 4ba5432d2..2250e588e 100644
--- a/app/models/invite.rb
+++ b/app/models/invite.rb
@@ -3,8 +3,8 @@
#
# Table name: invites
#
-# id :integer not null, primary key
-# user_id :integer not null
+# id :bigint(8) not null, primary key
+# user_id :bigint(8) not null
# code :string default(""), not null
# expires_at :datetime
# max_uses :integer
diff --git a/app/models/list.rb b/app/models/list.rb
index a2ec7e84a..c9c94fca1 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -3,8 +3,8 @@
#
# Table name: lists
#
-# id :integer not null, primary key
-# account_id :integer not null
+# id :bigint(8) not null, primary key
+# account_id :bigint(8) not null
# title :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
diff --git a/app/models/list_account.rb b/app/models/list_account.rb
index da46cf032..87b498224 100644
--- a/app/models/list_account.rb
+++ b/app/models/list_account.rb
@@ -3,10 +3,10 @@
#
# Table name: list_accounts
#
-# id :integer not null, primary key
-# list_id :integer not null
-# account_id :integer not null
-# follow_id :integer not null
+# id :bigint(8) not null, primary key
+# list_id :bigint(8) not null
+# account_id :bigint(8) not null
+# follow_id :bigint(8) not null
#
class ListAccount < ApplicationRecord
diff --git a/app/models/media_attachment.rb b/app/models/media_attachment.rb
index c9abab9e2..f9a8f322e 100644
--- a/app/models/media_attachment.rb
+++ b/app/models/media_attachment.rb
@@ -3,8 +3,8 @@
#
# Table name: media_attachments
#
-# id :integer not null, primary key
-# status_id :integer
+# id :bigint(8) not null, primary key
+# status_id :bigint(8)
# file_file_name :string
# file_content_type :string
# file_file_size :integer
@@ -15,7 +15,7 @@
# shortcode :string
# type :integer default("image"), not null
# file_meta :json
-# account_id :integer
+# account_id :bigint(8)
# description :text
#
diff --git a/app/models/mention.rb b/app/models/mention.rb
index f864bf8e1..8ab886b18 100644
--- a/app/models/mention.rb
+++ b/app/models/mention.rb
@@ -3,11 +3,11 @@
#
# Table name: mentions
#
-# id :integer not null, primary key
-# status_id :integer
+# id :bigint(8) not null, primary key
+# status_id :bigint(8)
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer
+# account_id :bigint(8)
#
class Mention < ApplicationRecord
diff --git a/app/models/mute.rb b/app/models/mute.rb
index 8efa27ac0..0e00c2278 100644
--- a/app/models/mute.rb
+++ b/app/models/mute.rb
@@ -3,11 +3,11 @@
#
# Table name: mutes
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# target_account_id :integer not null
+# account_id :bigint(8) not null
+# target_account_id :bigint(8) not null
# hide_notifications :boolean default(TRUE), not null
#
diff --git a/app/models/notification.rb b/app/models/notification.rb
index 0b0f01aa8..4f6ec8e8e 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -3,13 +3,13 @@
#
# Table name: notifications
#
-# id :integer not null, primary key
-# activity_id :integer not null
+# id :bigint(8) not null, primary key
+# activity_id :bigint(8) not null
# activity_type :string not null
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# from_account_id :integer not null
+# account_id :bigint(8) not null
+# from_account_id :bigint(8) not null
#
class Notification < ApplicationRecord
diff --git a/app/models/preview_card.rb b/app/models/preview_card.rb
index 0ffa6b10f..a792b352b 100644
--- a/app/models/preview_card.rb
+++ b/app/models/preview_card.rb
@@ -3,7 +3,7 @@
#
# Table name: preview_cards
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# url :string default(""), not null
# title :string default(""), not null
# description :string default(""), not null
diff --git a/app/models/report.rb b/app/models/report.rb
index 5b90c7bce..efe385b2d 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -3,16 +3,16 @@
#
# Table name: reports
#
-# id :integer not null, primary key
-# status_ids :integer default([]), not null, is an Array
+# id :bigint(8) not null, primary key
+# status_ids :bigint(8) default([]), not null, is an Array
# comment :text default(""), not null
# action_taken :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
-# account_id :integer not null
-# action_taken_by_account_id :integer
-# target_account_id :integer not null
-# assigned_account_id :integer
+# account_id :bigint(8) not null
+# action_taken_by_account_id :bigint(8)
+# target_account_id :bigint(8) not null
+# assigned_account_id :bigint(8)
#
class Report < ApplicationRecord
diff --git a/app/models/report_note.rb b/app/models/report_note.rb
index 6d9dec80a..54b416577 100644
--- a/app/models/report_note.rb
+++ b/app/models/report_note.rb
@@ -3,10 +3,10 @@
#
# Table name: report_notes
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# content :text not null
-# report_id :integer not null
-# account_id :integer not null
+# report_id :bigint(8) not null
+# account_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
#
diff --git a/app/models/session_activation.rb b/app/models/session_activation.rb
index d364f03df..34d25c83d 100644
--- a/app/models/session_activation.rb
+++ b/app/models/session_activation.rb
@@ -3,15 +3,15 @@
#
# Table name: session_activations
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# session_id :string not null
# created_at :datetime not null
# updated_at :datetime not null
# user_agent :string default(""), not null
# ip :inet
-# access_token_id :integer
-# user_id :integer not null
-# web_push_subscription_id :integer
+# access_token_id :bigint(8)
+# user_id :bigint(8) not null
+# web_push_subscription_id :bigint(8)
#
class SessionActivation < ApplicationRecord
diff --git a/app/models/setting.rb b/app/models/setting.rb
index df93590ce..033d09fd5 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -3,13 +3,13 @@
#
# Table name: settings
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# var :string not null
# value :text
# thing_type :string
# created_at :datetime
# updated_at :datetime
-# thing_id :integer
+# thing_id :bigint(8)
#
class Setting < RailsSettings::Base
diff --git a/app/models/site_upload.rb b/app/models/site_upload.rb
index 641128adf..14d683767 100644
--- a/app/models/site_upload.rb
+++ b/app/models/site_upload.rb
@@ -3,7 +3,7 @@
#
# Table name: site_uploads
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# var :string default(""), not null
# file_file_name :string
# file_content_type :string
diff --git a/app/models/status.rb b/app/models/status.rb
index 62857dd6b..ed4bcefca 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -3,13 +3,13 @@
#
# Table name: statuses
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# uri :string
# text :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
-# in_reply_to_id :integer
-# reblog_of_id :integer
+# in_reply_to_id :bigint(8)
+# reblog_of_id :bigint(8)
# url :string
# sensitive :boolean default(FALSE), not null
# visibility :integer default("public"), not null
@@ -18,11 +18,11 @@
# favourites_count :integer default(0), not null
# reblogs_count :integer default(0), not null
# language :string
-# conversation_id :integer
+# conversation_id :bigint(8)
# local :boolean
-# account_id :integer not null
-# application_id :integer
-# in_reply_to_account_id :integer
+# account_id :bigint(8) not null
+# application_id :bigint(8)
+# in_reply_to_account_id :bigint(8)
#
class Status < ApplicationRecord
diff --git a/app/models/status_pin.rb b/app/models/status_pin.rb
index d3a98d8bd..afc76bded 100644
--- a/app/models/status_pin.rb
+++ b/app/models/status_pin.rb
@@ -3,9 +3,9 @@
#
# Table name: status_pins
#
-# id :integer not null, primary key
-# account_id :integer not null
-# status_id :integer not null
+# id :bigint(8) not null, primary key
+# account_id :bigint(8) not null
+# status_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
#
diff --git a/app/models/stream_entry.rb b/app/models/stream_entry.rb
index 2ae034d93..a2f273281 100644
--- a/app/models/stream_entry.rb
+++ b/app/models/stream_entry.rb
@@ -3,13 +3,13 @@
#
# Table name: stream_entries
#
-# id :integer not null, primary key
-# activity_id :integer
+# id :bigint(8) not null, primary key
+# activity_id :bigint(8)
# activity_type :string
# created_at :datetime not null
# updated_at :datetime not null
# hidden :boolean default(FALSE), not null
-# account_id :integer
+# account_id :bigint(8)
#
class StreamEntry < ApplicationRecord
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
index ea1173160..79b81828d 100644
--- a/app/models/subscription.rb
+++ b/app/models/subscription.rb
@@ -3,7 +3,7 @@
#
# Table name: subscriptions
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# callback_url :string default(""), not null
# secret :string
# expires_at :datetime
@@ -12,7 +12,7 @@
# updated_at :datetime not null
# last_successful_delivery_at :datetime
# domain :string
-# account_id :integer not null
+# account_id :bigint(8) not null
#
class Subscription < ApplicationRecord
diff --git a/app/models/tag.rb b/app/models/tag.rb
index 9fa9405d7..8b1b02412 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -3,7 +3,7 @@
#
# Table name: tags
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# name :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
diff --git a/app/models/user.rb b/app/models/user.rb
index 2d5f145fa..a9f3e1da2 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -3,7 +3,7 @@
#
# Table name: users
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# email :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
@@ -30,10 +30,10 @@
# last_emailed_at :datetime
# otp_backup_codes :string is an Array
# filtered_languages :string default([]), not null, is an Array
-# account_id :integer not null
+# account_id :bigint(8) not null
# disabled :boolean default(FALSE), not null
# moderator :boolean default(FALSE), not null
-# invite_id :integer
+# invite_id :bigint(8)
# remember_token :string
#
diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb
index 5aee92d27..1736106f7 100644
--- a/app/models/web/push_subscription.rb
+++ b/app/models/web/push_subscription.rb
@@ -3,7 +3,7 @@
#
# Table name: web_push_subscriptions
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# endpoint :string not null
# key_p256dh :string not null
# key_auth :string not null
diff --git a/app/models/web/setting.rb b/app/models/web/setting.rb
index 0a5129d17..99588d26c 100644
--- a/app/models/web/setting.rb
+++ b/app/models/web/setting.rb
@@ -3,11 +3,11 @@
#
# Table name: web_settings
#
-# id :integer not null, primary key
+# id :bigint(8) not null, primary key
# data :json
# created_at :datetime not null
# updated_at :datetime not null
-# user_id :integer not null
+# user_id :bigint(8) not null
#
class Web::Setting < ApplicationRecord
diff --git a/config/deploy.rb b/config/deploy.rb
index 180dd1c2a..e0cd60f54 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-lock '3.10.1'
+lock '3.10.2'
set :repo_url, ENV.fetch('REPO', 'https://github.com/tootsuite/mastodon.git')
set :branch, ENV.fetch('BRANCH', 'master')
From 3ccca6cece51fd071fed8c1e05af6a48c00c8897 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?=
Date: Mon, 23 Apr 2018 11:49:03 +0200
Subject: [PATCH 138/442] =?UTF-8?q?=F0=9F=8C=8D:=20Make=20=F0=9F=87=B5?=
=?UTF-8?q?=F0=9F=87=B1=20translation=20more=20consistent=20(#7239)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marcin Mikołajczak
---
app/javascript/mastodon/locales/pl.json | 10 +++++-----
config/locales/pl.yml | 12 +++++++-----
config/locales/simple_form.pl.yml | 2 +-
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json
index 22ae2de47..9dff9d1a3 100644
--- a/app/javascript/mastodon/locales/pl.json
+++ b/app/javascript/mastodon/locales/pl.json
@@ -103,8 +103,8 @@
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
"empty_column.direct": "Nie masz żadnych wiadomości bezpośrednich. Kiedy dostaniesz lub wyślesz jakąś, pojawi się ona tutaj.",
"empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy!",
- "empty_column.home": "Nie śledzisz nikogo. Odwiedź publiczną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
- "empty_column.home.public_timeline": "publiczna oś czasu",
+ "empty_column.home": "Nie śledzisz nikogo. Odwiedź globalną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.",
+ "empty_column.home.public_timeline": "globalna oś czasu",
"empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.",
"empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.",
"empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić",
@@ -169,7 +169,7 @@
"navigation_bar.mutes": "Wyciszeni użytkownicy",
"navigation_bar.pins": "Przypięte wpisy",
"navigation_bar.preferences": "Preferencje",
- "navigation_bar.public_timeline": "Oś czasu federacji",
+ "navigation_bar.public_timeline": "Globalna oś czasu",
"notification.favourite": "{name} dodał Twój wpis do ulubionych",
"notification.follow": "{name} zaczął Cię śledzić",
"notification.mention": "{name} wspomniał o tobie",
@@ -187,7 +187,7 @@
"notifications.column_settings.sound": "Odtwarzaj dźwięk",
"onboarding.done": "Gotowe",
"onboarding.next": "Dalej",
- "onboarding.page_five.public_timelines": "Lokalna oś czasu zawiera wszystkie publiczne wpisy z {domain}. Federalna oś czasu wyświetla publiczne wpisy śledzonych przez członków {domain}. Są to publiczne osie czasu – najlepszy sposób na poznanie nowych osób.",
+ "onboarding.page_five.public_timelines": "Lokalna oś czasu zawiera wszystkie publiczne wpisy z {domain}. Globalna oś czasu wyświetla publiczne wpisy śledzonych przez członków {domain}. Są to publiczne osie czasu – najlepszy sposób na poznanie nowych osób.",
"onboarding.page_four.home": "Główna oś czasu wyświetla publiczne wpisy.",
"onboarding.page_four.notifications": "Kolumna powiadomień wyświetla, gdy ktoś dokonuje interakcji z tobą.",
"onboarding.page_one.federation": "Mastodon jest siecią niezależnych serwerów połączonych w jeden portal społecznościowy. Nazywamy te serwery instancjami.",
@@ -247,7 +247,7 @@
"status.delete": "Usuń",
"status.direct": "Wyślij wiadomość bezpośrednią do @{name}",
"status.embed": "Osadź",
- "status.favourite": "Ulubione",
+ "status.favourite": "Dodaj do ulubionych",
"status.load_more": "Załaduj więcej",
"status.media_hidden": "Zawartość multimedialna ukryta",
"status.mention": "Wspomnij o @{name}",
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 839767c8f..71bf6bf18 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -466,7 +466,7 @@ pl:
archive_takeout:
date: Data
download: Pobierz swoje archiwum
- hint_html: Możesz uzyskać archiwum swoich wpisów i wysłanej zawartości multimedialnej. Wyeksportowane dane będą dostępne w formacie ActivityPub, obsługiwanym przez odpowiednie programy.
+ hint_html: Możesz uzyskać archiwum swoich wpisów i wysłanej zawartości multimedialnej. Wyeksportowane dane będą dostępne w formacie ActivityPub, który możesz otworzyć w obsługujących go programach.
in_progress: Tworzenie archiwum…
request: Uzyskaj archiwum
size: Rozmiar
@@ -485,17 +485,19 @@ pl:
one: W trakcie usuwania śledzących z jednej domeny…
other: W trakcie usuwania śledzących z %{count} domen…
true_privacy_html: Pamiętaj, że rzeczywista prywatność może zostać uzyskana wyłącznie dzięki szyfrowaniu end-to-end.
- unlocked_warning_html: Każdy może Cię śledzić, aby natychmiastowo zobaczyć twoje wpisy. %{lock_link} aby móc kontrolować, kto Cię śledzi.
+ unlocked_warning_html: Każdy może Cię śledzić, dzięki czemu może zobaczyć Twoje niepubliczne wpisy. %{lock_link} aby móc kontrolować, kto Cię śledzi.
unlocked_warning_title: Twoje konto nie jest zablokowane
generic:
changes_saved_msg: Ustawienia zapisane!
powered_by: uruchomione na %{link}
save_changes: Zapisz zmiany
validation_errors:
- one: Coś jest wciąż nie tak! Przyjrzyj się błędowi poniżej
- other: Coś jest wciąż nie tak! Przejrzyj błędy (%{count}) poniżej
+ few: Coś jest wciąż nie tak! Przejrzyj %{count} poniższe błędy
+ many: Coś jest wciąż nie tak! Przejrzyj %{count} poniższych błędów
+ one: Coś jest wciąż nie tak! Przyjrzyj się poniższemu błędowi
+ other: Coś jest wciąż nie tak! Przejrzyj poniższe błędy (%{count})
imports:
- preface: Możesz zaimportować pewne dane (jak dane kont, które śledzisz lub blokujesz) do swojego konta na tym serwerze, korzystając z danych wyeksportowanych z innego serwera.
+ preface: Możesz zaimportować pewne dane (np. lista kont, które śledzisz lub blokujesz) do swojego konta na tym serwerze, korzystając z danych wyeksportowanych z innego serwera.
success: Twoje dane zostały załadowane i zostaną niebawem przetworzone
types:
blocking: Lista blokowanych
diff --git a/config/locales/simple_form.pl.yml b/config/locales/simple_form.pl.yml
index cbca232fe..4c1833b1c 100644
--- a/config/locales/simple_form.pl.yml
+++ b/config/locales/simple_form.pl.yml
@@ -62,7 +62,7 @@ pl:
setting_theme: Motyw strony
setting_unfollow_modal: Pytaj o potwierdzenie przed cofnięciem śledzenia
severity: Priorytet
- type: Typ importu
+ type: Importowane dane
username: Nazwa użytkownika
username_or_email: Nazwa użytkownika lub adres e-mail
interactions:
From 06817b3c1fdcc9c2b3484478588cc348a4a06537 Mon Sep 17 00:00:00 2001
From: Alejandro Martinez Ruiz
Date: Mon, 23 Apr 2018 15:03:58 +0100
Subject: [PATCH 139/442] tasks/mastodon: fix prompt for Redis password (#7241)
---
lib/tasks/mastodon.rake | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/tasks/mastodon.rake b/lib/tasks/mastodon.rake
index b5a148337..7a337845e 100644
--- a/lib/tasks/mastodon.rake
+++ b/lib/tasks/mastodon.rake
@@ -109,7 +109,7 @@ namespace :mastodon do
env['REDIS_PASSWORD'] = prompt.ask('Redis password:') do |q|
q.required false
- a.default nil
+ q.default nil
q.modify :strip
end
From 1258efa882b7a0eedc868640eb8e5a9075445ca0 Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Tue, 24 Apr 2018 02:27:35 +0900
Subject: [PATCH 140/442] Paginate descendant statuses in public page (#7148)
---
app/controllers/api/v1/statuses_controller.rb | 2 +-
app/controllers/statuses_controller.rb | 73 ++++++++++++++++++-
.../concerns/status_threading_concern.rb | 17 +++--
app/views/stream_entries/_more.html.haml | 2 +
app/views/stream_entries/_status.html.haml | 15 +++-
spec/controllers/statuses_controller_spec.rb | 43 +++++++++++
.../concerns/status_threading_concern_spec.rb | 12 +--
.../stream_entries/show.html.haml_spec.rb | 4 +-
8 files changed, 146 insertions(+), 22 deletions(-)
create mode 100644 app/views/stream_entries/_more.html.haml
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index e98241323..01880565c 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -18,7 +18,7 @@ class Api::V1::StatusesController < Api::BaseController
def context
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(DEFAULT_STATUSES_LIMIT, current_account)
- descendants_results = @status.descendants(current_account)
+ descendants_results = @status.descendants(DEFAULT_STATUSES_LIMIT, current_account)
loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = cache_collection(descendants_results, Status)
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index a2943982a..01dac35e4 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -5,6 +5,8 @@ class StatusesController < ApplicationController
include Authorization
ANCESTORS_LIMIT = 20
+ DESCENDANTS_LIMIT = 20
+ DESCENDANTS_DEPTH_LIMIT = 4
layout 'public'
@@ -19,9 +21,8 @@ class StatusesController < ApplicationController
def show
respond_to do |format|
format.html do
- @ancestors = @status.reply? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT, current_account), Status) : []
- @next_ancestor = @ancestors.size < ANCESTORS_LIMIT ? nil : @ancestors.shift
- @descendants = cache_collection(@status.descendants(current_account), Status)
+ set_ancestors
+ set_descendants
render 'stream_entries/show'
end
@@ -51,10 +52,76 @@ class StatusesController < ApplicationController
private
+ def create_descendant_thread(depth, statuses)
+ if depth < DESCENDANTS_DEPTH_LIMIT
+ { statuses: statuses }
+ else
+ next_status = statuses.pop
+ { statuses: statuses, next_status: next_status }
+ end
+ end
+
def set_account
@account = Account.find_local!(params[:account_username])
end
+ def set_ancestors
+ @ancestors = @status.reply? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT, current_account), Status) : []
+ @next_ancestor = @ancestors.size < ANCESTORS_LIMIT ? nil : @ancestors.shift
+ end
+
+ def set_descendants
+ @max_descendant_thread_id = params[:max_descendant_thread_id]&.to_i
+ @since_descendant_thread_id = params[:since_descendant_thread_id]&.to_i
+
+ descendants = cache_collection(
+ @status.descendants(
+ DESCENDANTS_LIMIT,
+ current_account,
+ @max_descendant_thread_id,
+ @since_descendant_thread_id,
+ DESCENDANTS_DEPTH_LIMIT
+ ),
+ Status
+ )
+ @descendant_threads = []
+
+ if descendants.present?
+ statuses = [descendants.first]
+ depth = 1
+
+ descendants.drop(1).each_with_index do |descendant, index|
+ if descendants[index].id == descendant.in_reply_to_id
+ depth += 1
+ statuses << descendant
+ else
+ @descendant_threads << create_descendant_thread(depth, statuses)
+
+ @descendant_threads.reverse_each do |descendant_thread|
+ statuses = descendant_thread[:statuses]
+
+ index = statuses.find_index do |thread_status|
+ thread_status.id == descendant.in_reply_to_id
+ end
+
+ if index.present?
+ depth += index - statuses.size
+ break
+ end
+
+ depth -= statuses.size
+ end
+
+ statuses = [descendant]
+ end
+ end
+
+ @descendant_threads << create_descendant_thread(depth, statuses)
+ end
+
+ @max_descendant_thread_id = @descendant_threads.pop[:statuses].first.id if descendants.size >= DESCENDANTS_LIMIT
+ end
+
def set_link_headers
response.headers['Link'] = LinkHeader.new(
[
diff --git a/app/models/concerns/status_threading_concern.rb b/app/models/concerns/status_threading_concern.rb
index fffc095ee..a3fd34e94 100644
--- a/app/models/concerns/status_threading_concern.rb
+++ b/app/models/concerns/status_threading_concern.rb
@@ -7,8 +7,8 @@ module StatusThreadingConcern
find_statuses_from_tree_path(ancestor_ids(limit), account)
end
- def descendants(account = nil)
- find_statuses_from_tree_path(descendant_ids, account)
+ def descendants(limit, account = nil, max_child_id = nil, since_child_id = nil, depth = nil)
+ find_statuses_from_tree_path(descendant_ids(limit, max_child_id, since_child_id, depth), account)
end
private
@@ -46,26 +46,27 @@ module StatusThreadingConcern
SQL
end
- def descendant_ids
- descendant_statuses.pluck(:id)
+ def descendant_ids(limit, max_child_id, since_child_id, depth)
+ descendant_statuses(limit, max_child_id, since_child_id, depth).pluck(:id)
end
- def descendant_statuses
- Status.find_by_sql([<<-SQL.squish, id: id])
+ def descendant_statuses(limit, max_child_id, since_child_id, depth)
+ Status.find_by_sql([<<-SQL.squish, id: id, limit: limit, max_child_id: max_child_id, since_child_id: since_child_id, depth: depth])
WITH RECURSIVE search_tree(id, path)
AS (
SELECT id, ARRAY[id]
FROM statuses
- WHERE in_reply_to_id = :id
+ WHERE in_reply_to_id = :id AND COALESCE(id < :max_child_id, TRUE) AND COALESCE(id > :since_child_id, TRUE)
UNION ALL
SELECT statuses.id, path || statuses.id
FROM search_tree
JOIN statuses ON statuses.in_reply_to_id = search_tree.id
- WHERE NOT statuses.id = ANY(path)
+ WHERE COALESCE(array_length(path, 1) < :depth, TRUE) AND NOT statuses.id = ANY(path)
)
SELECT id
FROM search_tree
ORDER BY path
+ LIMIT :limit
SQL
end
diff --git a/app/views/stream_entries/_more.html.haml b/app/views/stream_entries/_more.html.haml
new file mode 100644
index 000000000..9b1dfe4a7
--- /dev/null
+++ b/app/views/stream_entries/_more.html.haml
@@ -0,0 +1,2 @@
+= link_to url, class: 'more light' do
+ = t('statuses.show_more')
diff --git a/app/views/stream_entries/_status.html.haml b/app/views/stream_entries/_status.html.haml
index 2d0dafcb7..8decdf6b5 100644
--- a/app/views/stream_entries/_status.html.haml
+++ b/app/views/stream_entries/_status.html.haml
@@ -16,8 +16,7 @@
- if status.reply? && include_threads
- if @next_ancestor
.entry{ class: entry_classes }
- = link_to short_account_status_url(@next_ancestor.account.username, @next_ancestor), class: 'more light' do
- = t('statuses.show_more')
+ = render 'stream_entries/more', url: short_account_status_url(@next_ancestor.account.username, @next_ancestor)
= render partial: 'stream_entries/status', collection: @ancestors, as: :status, locals: { is_predecessor: true, direct_reply_id: status.in_reply_to_id }
.entry{ class: entry_classes }
@@ -40,4 +39,14 @@
= render (centered ? 'stream_entries/detailed_status' : 'stream_entries/simple_status'), status: status.proper
- if include_threads
- = render partial: 'stream_entries/status', collection: @descendants, as: :status, locals: { is_successor: true, parent_id: status.id }
+ - if @since_descendant_thread_id
+ .entry{ class: entry_classes }
+ = render 'stream_entries/more', url: short_account_status_url(status.account.username, status, max_descendant_thread_id: @since_descendant_thread_id + 1)
+ - @descendant_threads.each do |thread|
+ = render partial: 'stream_entries/status', collection: thread[:statuses], as: :status, locals: { is_successor: true, parent_id: status.id }
+ - if thread[:next_status]
+ .entry{ class: entry_classes }
+ = render 'stream_entries/more', url: short_account_status_url(thread[:next_status].account.username, thread[:next_status])
+ - if @next_descendant_thread
+ .entry{ class: entry_classes }
+ = render 'stream_entries/more', url: short_account_status_url(status.account.username, status, since_descendant_thread_id: @max_descendant_thread_id - 1)
diff --git a/spec/controllers/statuses_controller_spec.rb b/spec/controllers/statuses_controller_spec.rb
index 89af55688..b4f3c5a08 100644
--- a/spec/controllers/statuses_controller_spec.rb
+++ b/spec/controllers/statuses_controller_spec.rb
@@ -82,6 +82,49 @@ describe StatusesController do
expect(assigns(:ancestors)).to eq []
end
+ it 'assigns @descendant_threads for a thread with several statuses' do
+ status = Fabricate(:status)
+ child = Fabricate(:status, in_reply_to_id: status.id)
+ grandchild = Fabricate(:status, in_reply_to_id: child.id)
+
+ get :show, params: { account_username: status.account.username, id: status.id }
+
+ expect(assigns(:descendant_threads)[0][:statuses].pluck(:id)).to eq [child.id, grandchild.id]
+ end
+
+ it 'assigns @descendant_threads for several threads sharing the same descendant' do
+ status = Fabricate(:status)
+ child = Fabricate(:status, in_reply_to_id: status.id)
+ grandchildren = 2.times.map { Fabricate(:status, in_reply_to_id: child.id) }
+
+ get :show, params: { account_username: status.account.username, id: status.id }
+
+ expect(assigns(:descendant_threads)[0][:statuses].pluck(:id)).to eq [child.id, grandchildren[0].id]
+ expect(assigns(:descendant_threads)[1][:statuses].pluck(:id)).to eq [grandchildren[1].id]
+ end
+
+ it 'assigns @max_descendant_thread_id for the last thread if it is hitting the status limit' do
+ stub_const 'StatusesController::DESCENDANTS_LIMIT', 1
+ status = Fabricate(:status)
+ child = Fabricate(:status, in_reply_to_id: status.id)
+
+ get :show, params: { account_username: status.account.username, id: status.id }
+
+ expect(assigns(:descendant_threads)).to eq []
+ expect(assigns(:max_descendant_thread_id)).to eq child.id
+ end
+
+ it 'assigns @descendant_threads for threads with :next_status key if they are hitting the depth limit' do
+ stub_const 'StatusesController::DESCENDANTS_DEPTH_LIMIT', 1
+ status = Fabricate(:status)
+ child = Fabricate(:status, in_reply_to_id: status.id)
+
+ get :show, params: { account_username: status.account.username, id: status.id }
+
+ expect(assigns(:descendant_threads)[0][:statuses].pluck(:id)).not_to include child.id
+ expect(assigns(:descendant_threads)[0][:next_status].id).to eq child.id
+ end
+
it 'returns a success' do
status = Fabricate(:status)
get :show, params: { account_username: status.account.username, id: status.id }
diff --git a/spec/models/concerns/status_threading_concern_spec.rb b/spec/models/concerns/status_threading_concern_spec.rb
index b8ebdd58c..e5736a307 100644
--- a/spec/models/concerns/status_threading_concern_spec.rb
+++ b/spec/models/concerns/status_threading_concern_spec.rb
@@ -89,34 +89,34 @@ describe StatusThreadingConcern do
let!(:viewer) { Fabricate(:account, username: 'viewer') }
it 'returns replies' do
- expect(status.descendants).to include(reply1, reply2, reply3)
+ expect(status.descendants(4)).to include(reply1, reply2, reply3)
end
it 'does not return replies user is not allowed to see' do
reply1.update(visibility: :private)
reply3.update(visibility: :direct)
- expect(status.descendants(viewer)).to_not include(reply1, reply3)
+ expect(status.descendants(4, viewer)).to_not include(reply1, reply3)
end
it 'does not return replies from blocked users' do
viewer.block!(jeff)
- expect(status.descendants(viewer)).to_not include(reply3)
+ expect(status.descendants(4, viewer)).to_not include(reply3)
end
it 'does not return replies from muted users' do
viewer.mute!(jeff)
- expect(status.descendants(viewer)).to_not include(reply3)
+ expect(status.descendants(4, viewer)).to_not include(reply3)
end
it 'does not return replies from silenced and not followed users' do
jeff.update(silenced: true)
- expect(status.descendants(viewer)).to_not include(reply3)
+ expect(status.descendants(4, viewer)).to_not include(reply3)
end
it 'does not return replies from blocked domains' do
viewer.block_domain!('example.com')
- expect(status.descendants(viewer)).to_not include(reply2)
+ expect(status.descendants(4, viewer)).to_not include(reply2)
end
end
end
diff --git a/spec/views/stream_entries/show.html.haml_spec.rb b/spec/views/stream_entries/show.html.haml_spec.rb
index 6074bbc2e..560039ffa 100644
--- a/spec/views/stream_entries/show.html.haml_spec.rb
+++ b/spec/views/stream_entries/show.html.haml_spec.rb
@@ -24,6 +24,7 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
assign(:stream_entry, status.stream_entry)
assign(:account, alice)
assign(:type, status.stream_entry.activity_type.downcase)
+ assign(:descendant_threads, [])
render
@@ -49,7 +50,7 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
assign(:account, alice)
assign(:type, reply.stream_entry.activity_type.downcase)
assign(:ancestors, reply.stream_entry.activity.ancestors(1, bob) )
- assign(:descendants, reply.stream_entry.activity.descendants(bob))
+ assign(:descendant_threads, [{ statuses: reply.stream_entry.activity.descendants(1)}])
render
@@ -75,6 +76,7 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
assign(:stream_entry, status.stream_entry)
assign(:account, alice)
assign(:type, status.stream_entry.activity_type.downcase)
+ assign(:descendant_threads, [])
render
From 53b1d8887325160934dec7557e97a43ce2896264 Mon Sep 17 00:00:00 2001
From: ThibG
Date: Mon, 23 Apr 2018 20:12:16 +0200
Subject: [PATCH 141/442] Fix fullscreen video player (fixes #7244) (#7245)
---
app/javascript/styles/mastodon/components.scss | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index c84e61306..f1284b388 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -4446,6 +4446,8 @@ a.status-card {
video {
max-width: 100% !important;
max-height: 100% !important;
+ width: 100% !important;
+ height: 100% !important;
}
}
From 495303d9b86919c72bf1948a714bf8d00b41fa0f Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Mon, 23 Apr 2018 21:27:18 +0200
Subject: [PATCH 142/442] Prevent suspended accounts from appearing in
AccountSearchService (#7246)
---
app/models/account.rb | 1 +
app/services/account_search_service.rb | 4 ++--
spec/services/account_search_service_spec.rb | 19 +++++++++++++++++++
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/app/models/account.rb b/app/models/account.rb
index 0a4370be4..ee47f04af 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -117,6 +117,7 @@ class Account < ApplicationRecord
scope :partitioned, -> { order(Arel.sql('row_number() over (partition by domain)')) }
scope :silenced, -> { where(silenced: true) }
scope :suspended, -> { where(suspended: true) }
+ scope :without_suspended, -> { where(suspended: false) }
scope :recent, -> { reorder(id: :desc) }
scope :alphabetic, -> { order(domain: :asc, username: :asc) }
scope :by_domain_accounts, -> { group(:domain).select(:domain, 'COUNT(*) AS accounts_count').order('accounts_count desc') }
diff --git a/app/services/account_search_service.rb b/app/services/account_search_service.rb
index 3860a9cbd..7edbd9b47 100644
--- a/app/services/account_search_service.rb
+++ b/app/services/account_search_service.rb
@@ -65,9 +65,9 @@ class AccountSearchService < BaseService
def exact_match
@_exact_match ||= begin
if domain_is_local?
- search_from.find_local(query_username)
+ search_from.without_suspended.find_local(query_username)
else
- search_from.find_remote(query_username, query_domain)
+ search_from.without_suspended.find_remote(query_username, query_domain)
end
end
end
diff --git a/spec/services/account_search_service_spec.rb b/spec/services/account_search_service_spec.rb
index 9bb27edad..c5ddc5844 100644
--- a/spec/services/account_search_service_spec.rb
+++ b/spec/services/account_search_service_spec.rb
@@ -137,5 +137,24 @@ describe AccountSearchService do
expect(service).not_to have_received(:call)
end
end
+
+ describe 'should not include suspended accounts' do
+ it 'returns the fuzzy match first, and does not return suspended exacts' do
+ partial = Fabricate(:account, username: 'exactness')
+ exact = Fabricate(:account, username: 'exact', suspended: true)
+
+ results = subject.call('exact', 10)
+ expect(results.size).to eq 1
+ expect(results).to eq [partial]
+ end
+
+ it "does not return suspended remote accounts" do
+ remote = Fabricate(:account, username: 'a', domain: 'remote', display_name: 'e', suspended: true)
+
+ results = subject.call('a@example.com', 2)
+ expect(results.size).to eq 0
+ expect(results).to eq []
+ end
+ end
end
end
From 60b871d56c554ddb22b7890d803e4ba6650ed286 Mon Sep 17 00:00:00 2001
From: Emelia Smith
Date: Mon, 23 Apr 2018 23:52:58 +0200
Subject: [PATCH 143/442] Implement the ability for instances to define a list
of disallowed hashtags (#7176)
The goal here isn't to prevent these hashtags from existing, but just to strongly curtail their usage; The hashtags may still exist in the database via federated status, or from being created prior to this feature.
---
app/models/status.rb | 1 +
.../disallowed_hashtags_validator.rb | 22 +++++++++++++++++++
config/locales/en.yml | 3 +++
config/settings.yml | 1 +
4 files changed, 27 insertions(+)
create mode 100644 app/validators/disallowed_hashtags_validator.rb
diff --git a/app/models/status.rb b/app/models/status.rb
index ed4bcefca..37f2db562 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -59,6 +59,7 @@ class Status < ApplicationRecord
validates :uri, uniqueness: true, presence: true, unless: :local?
validates :text, presence: true, unless: -> { with_media? || reblog? }
validates_with StatusLengthValidator
+ validates_with DisallowedHashtagsValidator
validates :reblog, uniqueness: { scope: :account }, if: :reblog?
default_scope { recent }
diff --git a/app/validators/disallowed_hashtags_validator.rb b/app/validators/disallowed_hashtags_validator.rb
new file mode 100644
index 000000000..22c027b0f
--- /dev/null
+++ b/app/validators/disallowed_hashtags_validator.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class DisallowedHashtagsValidator < ActiveModel::Validator
+ def validate(status)
+ return unless status.local? && !status.reblog?
+
+ tags = Extractor.extract_hashtags(status.text)
+ tags.keep_if { |tag| disallowed_hashtags.include? tag.downcase }
+
+ status.errors.add(:text, I18n.t('statuses.disallowed_hashtags', tags: tags.join(', '), count: tags.size)) unless tags.empty?
+ end
+
+ private
+
+ def disallowed_hashtags
+ return @disallowed_hashtags if @disallowed_hashtags
+
+ @disallowed_hashtags = Setting.disallowed_hashtags.nil? ? [] : Setting.disallowed_hashtags
+ @disallowed_hashtags = @disallowed_hashtags.split(' ') if @disallowed_hashtags.is_a? String
+ @disallowed_hashtags = @disallowed_hashtags.map(&:downcase)
+ end
+end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8b66b91ec..1468d8559 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -684,6 +684,9 @@ en:
one: "%{count} video"
other: "%{count} videos"
content_warning: 'Content warning: %{warning}'
+ disallowed_hashtags:
+ one: 'contained a disallowed hashtag: %{tags}'
+ other: 'contained the disallowed hashtags: %{tags}'
open_in_web: Open in web
over_character_limit: character limit of %{max} exceeded
pin_errors:
diff --git a/config/settings.yml b/config/settings.yml
index 68579ad0f..dcf655008 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -47,6 +47,7 @@ defaults: &defaults
- root
- webmaster
- administrator
+ disallowed_hashtags: # space separated string or list of hashtags without the hash
bootstrap_timeline_accounts: ''
activity_api_enabled: true
peers_api_enabled: true
From 306267dbd275363422f9288c91e634a92511620c Mon Sep 17 00:00:00 2001
From: Akihiko Odaki
Date: Tue, 24 Apr 2018 18:47:27 +0900
Subject: [PATCH 144/442] Fix ID duplication in timelines (#7251)
---
app/javascript/mastodon/reducers/timelines.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index ad897bcc9..dd675d78f 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -34,7 +34,7 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial) =>
mMap.update('items', ImmutableList(), oldIds => {
const newIds = statuses.map(status => status.get('id'));
const lastIndex = oldIds.findLastIndex(id => id !== null && compareId(id, newIds.last()) >= 0) + 1;
- const firstIndex = oldIds.take(lastIndex).findLastIndex(id => id !== null && compareId(id, newIds.first()) >= 0);
+ const firstIndex = oldIds.take(lastIndex).findLastIndex(id => id !== null && compareId(id, newIds.first()) > 0);
if (firstIndex < 0) {
return (isPartial ? newIds.unshift(null) : newIds).concat(oldIds.skip(lastIndex));
From 7681ad80449dafc6fb4572fa66c463930ef82f19 Mon Sep 17 00:00:00 2001
From: "Renato \"Lond\" Cerqueira"
Date: Tue, 24 Apr 2018 11:48:11 +0200
Subject: [PATCH 145/442] Weblate translations (2018-04-24) (#7252)
* Translated using Weblate (Dutch)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/nl/
* Translated using Weblate (French)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (626 of 626 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/nl/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/nl/
* Translated using Weblate (Japanese)
Currently translated at 99.6% (287 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/
* Translated using Weblate (Japanese)
Currently translated at 99.5% (623 of 626 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Galician)
Currently translated at 99.8% (625 of 626 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/
* Translated using Weblate (French)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/
* Translated using Weblate (French)
Currently translated at 99.6% (624 of 626 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fr/
* Translated using Weblate (French)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 99.5% (631 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/
* Translated using Weblate (Korean)
Currently translated at 99.8% (633 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ko/
* Translated using Weblate (Korean)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ko/
* Translated using Weblate (French)
Currently translated at 99.6% (632 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fr/
* Translated using Weblate (Japanese)
Currently translated at 99.6% (632 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (634 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (634 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/
* Translated using Weblate (Dutch)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/nl/
* Translated using Weblate (Japanese)
Currently translated at 93.5% (58 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ja/
* Added translation using Weblate (Basque)
* Added translation using Weblate (Basque)
* Translated using Weblate (Galician)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/gl/
* Added translation using Weblate (Basque)
* Added translation using Weblate (Basque)
* Added translation using Weblate (Basque)
* Added translation using Weblate (Basque)
* Translated using Weblate (Galician)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/gl/
* Translated using Weblate (Galician)
Currently translated at 99.8% (633 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/
* Translated using Weblate (Basque)
Currently translated at 0.3% (1 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/
* Translated using Weblate (Basque)
Currently translated at 50.0% (1 of 2 strings)
Translation: Mastodon/Activerecord
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/activerecord/eu/
* Translated using Weblate (Basque)
Currently translated at 1.6% (1 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/eu/
* Translated using Weblate (Basque)
Currently translated at 1.3% (1 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/eu/
* Translated using Weblate (Basque)
Currently translated at 1.6% (1 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/eu/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ca/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (634 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ca/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (634 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ca/
* Translated using Weblate (Catalan)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/
* Translated using Weblate (Japanese)
Currently translated at 93.5% (58 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ja/
* Translated using Weblate (Arabic)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ar/
* Translated using Weblate (Arabic)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/
* Translated using Weblate (Arabic)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ar/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/sk/
* Translated using Weblate (Japanese)
Currently translated at 93.5% (58 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/ja/
* Translated using Weblate (Slovak)
Currently translated at 99.6% (287 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Slovak)
Currently translated at 88.4% (561 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 90.3% (573 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Slovak)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/
* Translated using Weblate (Korean)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ko/
* Translated using Weblate (Italian)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/it/
* Translated using Weblate (Italian)
Currently translated at 3.2% (2 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/it/
* Translated using Weblate (Italian)
Currently translated at 100.0% (288 of 288 strings)
Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/it/
* Translated using Weblate (Italian)
Currently translated at 100.0% (75 of 75 strings)
Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/it/
* Translated using Weblate (Italian)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/it/
* Translated using Weblate (Italian)
Currently translated at 32.4% (206 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/it/
* Translated using Weblate (Italian)
Currently translated at 100.0% (62 of 62 strings)
Translation: Mastodon/Devise
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/devise/it/
* Translated using Weblate (Arabic)
Currently translated at 81.3% (516 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ar/
* Translated using Weblate (Italian)
Currently translated at 51.2% (325 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/it/
* Translated using Weblate (Slovak)
Currently translated at 91.6% (581 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/
* Translated using Weblate (Italian)
Currently translated at 51.8% (329 of 634 strings)
Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/it/
* Normalize translations
Ran yarn build:development && i18n-tasks normalize && yarn manage:translations
* Remove unused translations
Ran i18n-tasks remove-unused
---
app/javascript/mastodon/locales/ar.json | 17 +-
app/javascript/mastodon/locales/bg.json | 1 +
app/javascript/mastodon/locales/ca.json | 21 +-
app/javascript/mastodon/locales/de.json | 1 +
app/javascript/mastodon/locales/eo.json | 1 +
app/javascript/mastodon/locales/es.json | 1 +
app/javascript/mastodon/locales/eu.json | 296 +++++++++++++++++++
app/javascript/mastodon/locales/fa.json | 1 +
app/javascript/mastodon/locales/fi.json | 1 +
app/javascript/mastodon/locales/fr.json | 21 +-
app/javascript/mastodon/locales/gl.json | 3 +-
app/javascript/mastodon/locales/he.json | 1 +
app/javascript/mastodon/locales/hr.json | 1 +
app/javascript/mastodon/locales/hu.json | 1 +
app/javascript/mastodon/locales/hy.json | 1 +
app/javascript/mastodon/locales/id.json | 1 +
app/javascript/mastodon/locales/io.json | 1 +
app/javascript/mastodon/locales/it.json | 7 +-
app/javascript/mastodon/locales/ja.json | 4 +-
app/javascript/mastodon/locales/ko.json | 5 +-
app/javascript/mastodon/locales/nl.json | 17 +-
app/javascript/mastodon/locales/no.json | 1 +
app/javascript/mastodon/locales/oc.json | 1 +
app/javascript/mastodon/locales/pt-BR.json | 7 +-
app/javascript/mastodon/locales/pt.json | 1 +
app/javascript/mastodon/locales/ru.json | 1 +
app/javascript/mastodon/locales/sk.json | 15 +-
app/javascript/mastodon/locales/sr-Latn.json | 1 +
app/javascript/mastodon/locales/sr.json | 1 +
app/javascript/mastodon/locales/sv.json | 1 +
app/javascript/mastodon/locales/th.json | 1 +
app/javascript/mastodon/locales/tr.json | 1 +
app/javascript/mastodon/locales/uk.json | 1 +
app/javascript/mastodon/locales/zh-CN.json | 1 +
app/javascript/mastodon/locales/zh-HK.json | 1 +
app/javascript/mastodon/locales/zh-TW.json | 1 +
config/locales/activerecord.eu.yml | 9 +
config/locales/ca.yml | 121 +++++++-
config/locales/devise.eu.yml | 5 +
config/locales/devise.it.yml | 21 ++
config/locales/doorkeeper.eu.yml | 6 +
config/locales/doorkeeper.it.yml | 16 +-
config/locales/eu.yml | 1 +
config/locales/fr.yml | 45 ++-
config/locales/gl.yml | 44 ++-
config/locales/it.yml | 251 +++++++++++++++-
config/locales/ja.yml | 5 +-
config/locales/ko.yml | 44 ++-
config/locales/nl.yml | 121 +++++++-
config/locales/pt-BR.yml | 43 ++-
config/locales/simple_form.ar.yml | 12 +
config/locales/simple_form.ca.yml | 6 +
config/locales/simple_form.eu.yml | 6 +
config/locales/simple_form.fr.yml | 6 +
config/locales/simple_form.gl.yml | 6 +
config/locales/simple_form.it.yml | 84 ++++--
config/locales/simple_form.ja.yml | 8 +-
config/locales/simple_form.ko.yml | 6 +
config/locales/simple_form.nl.yml | 8 +-
config/locales/simple_form.sk.yml | 12 +-
config/locales/sk.yml | 22 +-
61 files changed, 1243 insertions(+), 103 deletions(-)
create mode 100644 app/javascript/mastodon/locales/eu.json
create mode 100644 config/locales/activerecord.eu.yml
create mode 100644 config/locales/devise.eu.yml
create mode 100644 config/locales/doorkeeper.eu.yml
create mode 100644 config/locales/eu.yml
create mode 100644 config/locales/simple_form.eu.yml
diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json
index 24c8a5b54..7975ac1c5 100644
--- a/app/javascript/mastodon/locales/ar.json
+++ b/app/javascript/mastodon/locales/ar.json
@@ -2,7 +2,7 @@
"account.block": "حظر @{name}",
"account.block_domain": "إخفاء كل شيئ قادم من إسم النطاق {domain}",
"account.blocked": "محظور",
- "account.direct": "Direct message @{name}",
+ "account.direct": "رسالة خاصة إلى @{name}",
"account.disclaimer_full": "قد لا تعكس المعلومات أدناه الملف الشخصي الكامل للمستخدم.",
"account.domain_blocked": "النطاق مخفي",
"account.edit_profile": "تعديل الملف الشخصي",
@@ -18,7 +18,7 @@
"account.mute_notifications": "كتم إخطارات @{name}",
"account.muted": "مكتوم",
"account.posts": "التبويقات",
- "account.posts_with_replies": "تبويقات تحتوي على رُدود",
+ "account.posts_with_replies": "التبويقات و الردود",
"account.report": "أبلغ عن @{name}",
"account.requested": "في انتظار الموافقة",
"account.share": "مشاركة @{name}'s profile",
@@ -29,8 +29,8 @@
"account.unmute": "إلغاء الكتم عن @{name}",
"account.unmute_notifications": "إلغاء كتم إخطارات @{name}",
"account.view_full_profile": "عرض الملف الشخصي كاملا",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "لقد طرأ هناك خطأ غير متوقّع.",
+ "alert.unexpected.title": "المعذرة !",
"boost_modal.combo": "يمكنك ضغط {combo} لتخطّي هذه في المرّة القادمة",
"bundle_column_error.body": "لقد وقع هناك خطأ أثناء عملية تحميل هذا العنصر.",
"bundle_column_error.retry": "إعادة المحاولة",
@@ -41,7 +41,7 @@
"column.blocks": "الحسابات المحجوبة",
"column.community": "الخيط العام المحلي",
"column.direct": "Direct messages",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "النطاقات المخفية",
"column.favourites": "المفضلة",
"column.follow_requests": "طلبات المتابعة",
"column.home": "الرئيسية",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "لذِكر الناشر",
"keyboard_shortcuts.reply": "للردّ",
"keyboard_shortcuts.search": "للتركيز على البحث",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "لتحرير تبويق جديد",
"keyboard_shortcuts.unfocus": "لإلغاء التركيز على حقل النص أو نافذة البحث",
"keyboard_shortcuts.up": "للإنتقال إلى أعلى القائمة",
@@ -157,7 +158,7 @@
"navigation_bar.blocks": "الحسابات المحجوبة",
"navigation_bar.community_timeline": "الخيط العام المحلي",
"navigation_bar.direct": "Direct messages",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "النطاقات المخفية",
"navigation_bar.edit_profile": "تعديل الملف الشخصي",
"navigation_bar.favourites": "المفضلة",
"navigation_bar.follow_requests": "طلبات المتابعة",
@@ -244,7 +245,7 @@
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "تعذرت ترقية هذا المنشور",
"status.delete": "إحذف",
- "status.direct": "Direct message @{name}",
+ "status.direct": "رسالة خاصة إلى @{name}",
"status.embed": "إدماج",
"status.favourite": "أضف إلى المفضلة",
"status.load_more": "حمّل المزيد",
@@ -275,7 +276,7 @@
"tabs_bar.home": "الرئيسية",
"tabs_bar.local_timeline": "المحلي",
"tabs_bar.notifications": "الإخطارات",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "البحث",
"ui.beforeunload": "سوف تفقد مسودتك إن تركت ماستدون.",
"upload_area.title": "إسحب ثم أفلت للرفع",
"upload_button.label": "إضافة وسائط",
diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json
index 25ef6db65..971475114 100644
--- a/app/javascript/mastodon/locales/bg.json
+++ b/app/javascript/mastodon/locales/bg.json
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json
index 6a44808e0..2e5004cc9 100644
--- a/app/javascript/mastodon/locales/ca.json
+++ b/app/javascript/mastodon/locales/ca.json
@@ -2,7 +2,7 @@
"account.block": "Bloca @{name}",
"account.block_domain": "Amaga-ho tot de {domain}",
"account.blocked": "Bloquejat",
- "account.direct": "Direct message @{name}",
+ "account.direct": "Missatge directe @{name}",
"account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.",
"account.domain_blocked": "Domini ocult",
"account.edit_profile": "Edita el perfil",
@@ -18,7 +18,7 @@
"account.mute_notifications": "Notificacions desactivades de @{name}",
"account.muted": "Silenciat",
"account.posts": "Toots",
- "account.posts_with_replies": "Toots amb respostes",
+ "account.posts_with_replies": "Toots i respostes",
"account.report": "Informe @{name}",
"account.requested": "Esperant aprovació. Clic per a cancel·lar la petició de seguiment",
"account.share": "Comparteix el perfil de @{name}",
@@ -29,8 +29,8 @@
"account.unmute": "Treure silenci de @{name}",
"account.unmute_notifications": "Activar notificacions de @{name}",
"account.view_full_profile": "Mostra el perfil complet",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "S'ha produït un error inesperat.",
+ "alert.unexpected.title": "Vaja!",
"boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop",
"bundle_column_error.body": "S'ha produït un error en carregar aquest component.",
"bundle_column_error.retry": "Torna-ho a provar",
@@ -41,7 +41,7 @@
"column.blocks": "Usuaris blocats",
"column.community": "Línia de temps local",
"column.direct": "Direct messages",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "Dominis ocults",
"column.favourites": "Favorits",
"column.follow_requests": "Peticions per seguir-te",
"column.home": "Inici",
@@ -59,7 +59,7 @@
"column_header.unpin": "No fixis",
"column_subheading.navigation": "Navegació",
"column_subheading.settings": "Configuració",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "compose_form.direct_message_warning": "Aquest toot només serà visible per a tots els usuaris esmentats.",
"compose_form.hashtag_warning": "Aquest toot no es mostrarà en cap etiqueta ja que no està llistat. Només els toots públics poden ser cercats per etiqueta.",
"compose_form.lock_disclaimer": "El teu compte no està bloquejat {locked}. Tothom pot seguir-te i veure els teus missatges a seguidors.",
"compose_form.lock_disclaimer.lock": "blocat",
@@ -68,7 +68,7 @@
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "Mèdia marcat com a sensible",
"compose_form.sensitive.unmarked": "Mèdia no està marcat com a sensible",
- "compose_form.spoiler.marked": "Text ocult sota l'avís",
+ "compose_form.spoiler.marked": "Text es ocult sota l'avís",
"compose_form.spoiler.unmarked": "Text no ocult",
"compose_form.spoiler_placeholder": "Escriu l'avís aquí",
"confirmation_modal.cancel": "Cancel·la",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "per esmentar l'autor",
"keyboard_shortcuts.reply": "respondre",
"keyboard_shortcuts.search": "per centrar la cerca",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "per a començar un toot nou de trinca",
"keyboard_shortcuts.unfocus": "descentrar l'area de composició de text/cerca",
"keyboard_shortcuts.up": "moure amunt en la llista",
@@ -157,7 +158,7 @@
"navigation_bar.blocks": "Usuaris bloquejats",
"navigation_bar.community_timeline": "Línia de temps Local",
"navigation_bar.direct": "Direct messages",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "Dominis ocults",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favorits",
"navigation_bar.follow_requests": "Sol·licituds de seguiment",
@@ -244,7 +245,7 @@
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Aquesta publicació no pot ser retootejada",
"status.delete": "Esborrar",
- "status.direct": "Direct message @{name}",
+ "status.direct": "Missatge directe @{name}",
"status.embed": "Incrustar",
"status.favourite": "Favorit",
"status.load_more": "Carrega més",
@@ -275,7 +276,7 @@
"tabs_bar.home": "Inici",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificacions",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "Cerca",
"ui.beforeunload": "El vostre esborrany es perdrà si sortiu de Mastodon.",
"upload_area.title": "Arrossega i deixa anar per carregar",
"upload_button.label": "Afegir multimèdia",
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index 69c2ae8d8..5ce90812e 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "um Autor_in zu erwähnen",
"keyboard_shortcuts.reply": "um zu antworten",
"keyboard_shortcuts.search": "um die Suche zu fokussieren",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "um einen neuen Toot zu beginnen",
"keyboard_shortcuts.unfocus": "um das Textfeld/die Suche nicht mehr zu fokussieren",
"keyboard_shortcuts.up": "sich in der Liste hinauf bewegen",
diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json
index e51163971..37587c14c 100644
--- a/app/javascript/mastodon/locales/eo.json
+++ b/app/javascript/mastodon/locales/eo.json
@@ -135,6 +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.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",
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 61ea0588d..41d7db9da 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "para mencionar al autor",
"keyboard_shortcuts.reply": "para responder",
"keyboard_shortcuts.search": "para poner el foco en la búsqueda",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "para comenzar un nuevo toot",
"keyboard_shortcuts.unfocus": "para retirar el foco de la caja de redacción/búsqueda",
"keyboard_shortcuts.up": "para ir hacia arriba en la lista",
diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json
new file mode 100644
index 000000000..02b7bf7e5
--- /dev/null
+++ b/app/javascript/mastodon/locales/eu.json
@@ -0,0 +1,296 @@
+{
+ "account.block": "Block @{name}",
+ "account.block_domain": "Hide everything from {domain}",
+ "account.blocked": "Blokeatuta",
+ "account.direct": "Direct message @{name}",
+ "account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
+ "account.domain_blocked": "Domain hidden",
+ "account.edit_profile": "Edit profile",
+ "account.follow": "Follow",
+ "account.followers": "Followers",
+ "account.follows": "Follows",
+ "account.follows_you": "Follows you",
+ "account.hide_reblogs": "Hide boosts from @{name}",
+ "account.media": "Media",
+ "account.mention": "Mention @{name}",
+ "account.moved_to": "{name} has moved to:",
+ "account.mute": "Mute @{name}",
+ "account.mute_notifications": "Mute notifications from @{name}",
+ "account.muted": "Muted",
+ "account.posts": "Toots",
+ "account.posts_with_replies": "Toots and replies",
+ "account.report": "Report @{name}",
+ "account.requested": "Awaiting approval. Click to cancel follow request",
+ "account.share": "Share @{name}'s profile",
+ "account.show_reblogs": "Show boosts from @{name}",
+ "account.unblock": "Unblock @{name}",
+ "account.unblock_domain": "Unhide {domain}",
+ "account.unfollow": "Unfollow",
+ "account.unmute": "Unmute @{name}",
+ "account.unmute_notifications": "Unmute notifications from @{name}",
+ "account.view_full_profile": "View full profile",
+ "alert.unexpected.message": "An unexpected error occurred.",
+ "alert.unexpected.title": "Oops!",
+ "boost_modal.combo": "You can press {combo} to skip this next time",
+ "bundle_column_error.body": "Something went wrong while loading this component.",
+ "bundle_column_error.retry": "Try again",
+ "bundle_column_error.title": "Network error",
+ "bundle_modal_error.close": "Close",
+ "bundle_modal_error.message": "Something went wrong while loading this component.",
+ "bundle_modal_error.retry": "Try again",
+ "column.blocks": "Blocked users",
+ "column.community": "Local timeline",
+ "column.direct": "Direct messages",
+ "column.domain_blocks": "Hidden domains",
+ "column.favourites": "Favourites",
+ "column.follow_requests": "Follow requests",
+ "column.home": "Home",
+ "column.lists": "Lists",
+ "column.mutes": "Muted users",
+ "column.notifications": "Notifications",
+ "column.pins": "Pinned toot",
+ "column.public": "Federated timeline",
+ "column_back_button.label": "Back",
+ "column_header.hide_settings": "Hide settings",
+ "column_header.moveLeft_settings": "Move column to the left",
+ "column_header.moveRight_settings": "Move column to the right",
+ "column_header.pin": "Pin",
+ "column_header.show_settings": "Show settings",
+ "column_header.unpin": "Unpin",
+ "column_subheading.navigation": "Navigation",
+ "column_subheading.settings": "Settings",
+ "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "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.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
+ "compose_form.lock_disclaimer.lock": "locked",
+ "compose_form.placeholder": "What is on your mind?",
+ "compose_form.publish": "Toot",
+ "compose_form.publish_loud": "{publish}!",
+ "compose_form.sensitive.marked": "Media is marked as sensitive",
+ "compose_form.sensitive.unmarked": "Media is not marked as sensitive",
+ "compose_form.spoiler.marked": "Text is hidden behind warning",
+ "compose_form.spoiler.unmarked": "Text is not hidden",
+ "compose_form.spoiler_placeholder": "Write your warning here",
+ "confirmation_modal.cancel": "Cancel",
+ "confirmations.block.confirm": "Block",
+ "confirmations.block.message": "Are you sure you want to block {name}?",
+ "confirmations.delete.confirm": "Delete",
+ "confirmations.delete.message": "Are you sure you want to delete this status?",
+ "confirmations.delete_list.confirm": "Delete",
+ "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
+ "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",
+ "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",
+ "keyboard_shortcuts.description": "Description",
+ "keyboard_shortcuts.down": "to move down in the list",
+ "keyboard_shortcuts.enter": "to open status",
+ "keyboard_shortcuts.favourite": "to 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.unfocus": "to un-focus compose textarea/search",
+ "keyboard_shortcuts.up": "to move up in the list",
+ "lightbox.close": "Close",
+ "lightbox.next": "Next",
+ "lightbox.previous": "Previous",
+ "lists.account.add": "Add to list",
+ "lists.account.remove": "Remove from list",
+ "lists.delete": "Delete list",
+ "lists.edit": "Edit list",
+ "lists.new.create": "Add list",
+ "lists.new.title_placeholder": "New list title",
+ "lists.search": "Search among people you follow",
+ "lists.subheading": "Your lists",
+ "loading_indicator.label": "Loading...",
+ "media_gallery.toggle_visible": "Toggle visibility",
+ "missing_indicator.label": "Not found",
+ "missing_indicator.sublabel": "This resource could not be found",
+ "mute_modal.hide_notifications": "Hide notifications from this user?",
+ "navigation_bar.blocks": "Blocked users",
+ "navigation_bar.community_timeline": "Local timeline",
+ "navigation_bar.direct": "Direct messages",
+ "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.edit_profile": "Edit profile",
+ "navigation_bar.favourites": "Favourites",
+ "navigation_bar.follow_requests": "Follow requests",
+ "navigation_bar.info": "Extended information",
+ "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
+ "navigation_bar.lists": "Lists",
+ "navigation_bar.logout": "Logout",
+ "navigation_bar.mutes": "Muted users",
+ "navigation_bar.pins": "Pinned toots",
+ "navigation_bar.preferences": "Preferences",
+ "navigation_bar.public_timeline": "Federated timeline",
+ "notification.favourite": "{name} favourited your status",
+ "notification.follow": "{name} followed you",
+ "notification.mention": "{name} mentioned you",
+ "notification.reblog": "{name} boosted your status",
+ "notifications.clear": "Clear notifications",
+ "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
+ "notifications.column_settings.alert": "Desktop notifications",
+ "notifications.column_settings.favourite": "Favourites:",
+ "notifications.column_settings.follow": "New followers:",
+ "notifications.column_settings.mention": "Mentions:",
+ "notifications.column_settings.push": "Push notifications",
+ "notifications.column_settings.push_meta": "This device",
+ "notifications.column_settings.reblog": "Boosts:",
+ "notifications.column_settings.show": "Show in column",
+ "notifications.column_settings.sound": "Play sound",
+ "onboarding.done": "Done",
+ "onboarding.next": "Next",
+ "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",
+ "onboarding.page_four.home": "The home timeline shows posts from people you follow.",
+ "onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
+ "onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
+ "onboarding.page_one.full_handle": "Your full handle",
+ "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
+ "onboarding.page_one.welcome": "Welcome to Mastodon!",
+ "onboarding.page_six.admin": "Your instance's admin is {admin}.",
+ "onboarding.page_six.almost_done": "Almost done...",
+ "onboarding.page_six.appetoot": "Bon Appetoot!",
+ "onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.",
+ "onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
+ "onboarding.page_six.guidelines": "community guidelines",
+ "onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
+ "onboarding.page_six.various_app": "mobile apps",
+ "onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.",
+ "onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.",
+ "onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.",
+ "onboarding.skip": "Skip",
+ "privacy.change": "Adjust status privacy",
+ "privacy.direct.long": "Post to mentioned users only",
+ "privacy.direct.short": "Direct",
+ "privacy.private.long": "Post to followers only",
+ "privacy.private.short": "Followers-only",
+ "privacy.public.long": "Post to public timelines",
+ "privacy.public.short": "Public",
+ "privacy.unlisted.long": "Do not show in public timelines",
+ "privacy.unlisted.short": "Unlisted",
+ "regeneration_indicator.label": "Loading…",
+ "regeneration_indicator.sublabel": "Your home feed is being prepared!",
+ "relative_time.days": "{number}d",
+ "relative_time.hours": "{number}h",
+ "relative_time.just_now": "now",
+ "relative_time.minutes": "{number}m",
+ "relative_time.seconds": "{number}s",
+ "reply_indicator.cancel": "Cancel",
+ "report.forward": "Forward to {target}",
+ "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
+ "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
+ "report.placeholder": "Additional comments",
+ "report.submit": "Submit",
+ "report.target": "Report {target}",
+ "search.placeholder": "Search",
+ "search_popout.search_format": "Advanced search format",
+ "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": "status",
+ "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
+ "search_popout.tips.user": "user",
+ "search_results.accounts": "People",
+ "search_results.hashtags": "Hashtags",
+ "search_results.statuses": "Toots",
+ "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
+ "standalone.public_title": "A look inside...",
+ "status.block": "Block @{name}",
+ "status.cancel_reblog_private": "Unboost",
+ "status.cannot_reblog": "This post cannot be boosted",
+ "status.delete": "Delete",
+ "status.direct": "Direct message @{name}",
+ "status.embed": "Embed",
+ "status.favourite": "Favourite",
+ "status.load_more": "Load more",
+ "status.media_hidden": "Media hidden",
+ "status.mention": "Mention @{name}",
+ "status.more": "More",
+ "status.mute": "Mute @{name}",
+ "status.mute_conversation": "Mute conversation",
+ "status.open": "Expand this status",
+ "status.pin": "Pin on profile",
+ "status.pinned": "Pinned toot",
+ "status.reblog": "Boost",
+ "status.reblog_private": "Boost to original audience",
+ "status.reblogged_by": "{name} boosted",
+ "status.reply": "Reply",
+ "status.replyAll": "Reply to thread",
+ "status.report": "Report @{name}",
+ "status.sensitive_toggle": "Click to view",
+ "status.sensitive_warning": "Sensitive content",
+ "status.share": "Share",
+ "status.show_less": "Show less",
+ "status.show_less_all": "Show less for all",
+ "status.show_more": "Show more",
+ "status.show_more_all": "Show more for all",
+ "status.unmute_conversation": "Unmute conversation",
+ "status.unpin": "Unpin from profile",
+ "tabs_bar.federated_timeline": "Federated",
+ "tabs_bar.home": "Home",
+ "tabs_bar.local_timeline": "Local",
+ "tabs_bar.notifications": "Notifications",
+ "tabs_bar.search": "Search",
+ "ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
+ "upload_area.title": "Drag & drop to upload",
+ "upload_button.label": "Add media",
+ "upload_form.description": "Describe for the visually impaired",
+ "upload_form.focus": "Crop",
+ "upload_form.undo": "Undo",
+ "upload_progress.label": "Uploading...",
+ "video.close": "Close video",
+ "video.exit_fullscreen": "Exit full screen",
+ "video.expand": "Expand video",
+ "video.fullscreen": "Full screen",
+ "video.hide": "Hide video",
+ "video.mute": "Mute sound",
+ "video.pause": "Pause",
+ "video.play": "Play",
+ "video.unmute": "Unmute sound"
+}
diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json
index cfe93007d..99aba00c3 100644
--- a/app/javascript/mastodon/locales/fa.json
+++ b/app/javascript/mastodon/locales/fa.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "برای نامبردن از نویسنده",
"keyboard_shortcuts.reply": "برای پاسخدادن",
"keyboard_shortcuts.search": "برای فعالکردن جستجو",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "برای آغاز یک بوق تازه",
"keyboard_shortcuts.unfocus": "برای برداشتن توجه از نوشتن/جستجو",
"keyboard_shortcuts.up": "برای بالا رفتن در فهرست",
diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json
index 1677c3c6c..07d4d9aa5 100644
--- a/app/javascript/mastodon/locales/fi.json
+++ b/app/javascript/mastodon/locales/fi.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "mainitse julkaisija",
"keyboard_shortcuts.reply": "vastaa",
"keyboard_shortcuts.search": "siirry hakukenttään",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "ala kirjoittaa uutta tuuttausta",
"keyboard_shortcuts.unfocus": "siirry pois tekstikentästä tai hakukentästä",
"keyboard_shortcuts.up": "siirry listassa ylöspäin",
diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json
index 9a9e8ab79..0343cc618 100644
--- a/app/javascript/mastodon/locales/fr.json
+++ b/app/javascript/mastodon/locales/fr.json
@@ -2,7 +2,7 @@
"account.block": "Bloquer @{name}",
"account.block_domain": "Tout masquer venant de {domain}",
"account.blocked": "Bloqué",
- "account.direct": "Direct message @{name}",
+ "account.direct": "Message direct @{name}",
"account.disclaimer_full": "Les données ci-dessous peuvent ne pas refléter ce profil dans sa totalité.",
"account.domain_blocked": "Domaine caché",
"account.edit_profile": "Modifier le profil",
@@ -18,7 +18,7 @@
"account.mute_notifications": "Ignorer les notifications de @{name}",
"account.muted": "Silencé",
"account.posts": "Pouets",
- "account.posts_with_replies": "Pouets avec réponses",
+ "account.posts_with_replies": "Pouets et réponses",
"account.report": "Signaler",
"account.requested": "En attente d'approbation. Cliquez pour annuler la requête",
"account.share": "Partager le profil de @{name}",
@@ -29,8 +29,8 @@
"account.unmute": "Ne plus masquer",
"account.unmute_notifications": "Réactiver les notifications de @{name}",
"account.view_full_profile": "Afficher le profil complet",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "Une erreur non-attendue s'est produite.",
+ "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",
@@ -41,7 +41,7 @@
"column.blocks": "Comptes bloqués",
"column.community": "Fil public local",
"column.direct": "Direct messages",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "Domaines cachés",
"column.favourites": "Favoris",
"column.follow_requests": "Demandes de suivi",
"column.home": "Accueil",
@@ -59,7 +59,7 @@
"column_header.unpin": "Retirer",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Paramètres",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "compose_form.direct_message_warning": "Ce pouet sera uniquement visible à tous les utilisateurs mentionnés.",
"compose_form.hashtag_warning": "Ce pouet ne sera pas listé dans les recherches par hashtag car sa visibilité est réglée sur \"non-listé\". Seuls les pouets avec une visibilité \"publique\" peuvent être recherchés par hashtag.",
"compose_form.lock_disclaimer": "Votre compte n’est pas {locked}. Tout le monde peut vous suivre et voir vos pouets privés.",
"compose_form.lock_disclaimer.lock": "verrouillé",
@@ -105,7 +105,7 @@
"empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag.",
"empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres personnes.",
"empty_column.home.public_timeline": "le fil public",
- "empty_column.list": "Il n'y a rien dans cette liste pour l'instant. Dès que des personnes de cette liste publieront de nouveaux statuts, ils apparaîtront ici.",
+ "empty_column.list": "Il n'y a rien dans cette liste pour l'instant. Dès que des personnes de cette liste publierons de nouveaux statuts, ils apparaîtront ici.",
"empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres personnes pour débuter la conversation.",
"empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des personnes d’autres instances pour remplir le fil public",
"follow_request.authorize": "Accepter",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "pour mentionner l'auteur",
"keyboard_shortcuts.reply": "pour répondre",
"keyboard_shortcuts.search": "pour cibler la recherche",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "pour démarrer un tout nouveau pouet",
"keyboard_shortcuts.unfocus": "pour recentrer composer textarea/search",
"keyboard_shortcuts.up": "pour remonter dans la liste",
@@ -157,7 +158,7 @@
"navigation_bar.blocks": "Comptes bloqués",
"navigation_bar.community_timeline": "Fil public local",
"navigation_bar.direct": "Direct messages",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "Domaines cachés",
"navigation_bar.edit_profile": "Modifier le profil",
"navigation_bar.favourites": "Favoris",
"navigation_bar.follow_requests": "Demandes de suivi",
@@ -244,7 +245,7 @@
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Cette publication ne peut être boostée",
"status.delete": "Effacer",
- "status.direct": "Direct message @{name}",
+ "status.direct": "Message direct @{name}",
"status.embed": "Intégrer",
"status.favourite": "Ajouter aux favoris",
"status.load_more": "Charger plus",
@@ -275,7 +276,7 @@
"tabs_bar.home": "Accueil",
"tabs_bar.local_timeline": "Fil public local",
"tabs_bar.notifications": "Notifications",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "Chercher",
"ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
"upload_area.title": "Glissez et déposez pour envoyer",
"upload_button.label": "Joindre un média",
diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json
index fca42374d..f7ad3e590 100644
--- a/app/javascript/mastodon/locales/gl.json
+++ b/app/javascript/mastodon/locales/gl.json
@@ -18,7 +18,7 @@
"account.mute_notifications": "Acalar as notificacións de @{name}",
"account.muted": "Muted",
"account.posts": "Toots",
- "account.posts_with_replies": "Toots with replies",
+ "account.posts_with_replies": "Toots e respostas",
"account.report": "Informar sobre @{name}",
"account.requested": "Agardando aceptación. Pulse para cancelar a solicitude de seguimento",
"account.share": "Compartir o perfil de @{name}",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "para mencionar o autor",
"keyboard_shortcuts.reply": "para responder",
"keyboard_shortcuts.search": "para centrar a busca",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "escribir un toot novo",
"keyboard_shortcuts.unfocus": "quitar o foco do área de escritura/busca",
"keyboard_shortcuts.up": "ir hacia arriba na lista",
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index e3e87f1d0..0ffbb14f3 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "לאזכר את המחבר(ת)",
"keyboard_shortcuts.reply": "לענות",
"keyboard_shortcuts.search": "להתמקד בחלון החיפוש",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "להתחיל חיצרוץ חדש",
"keyboard_shortcuts.unfocus": "לצאת מתיבת חיבור/חיפוש",
"keyboard_shortcuts.up": "לנוע במעלה הרשימה",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index b41c98394..c41cc3ea1 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json
index 956accc67..a0c186184 100644
--- a/app/javascript/mastodon/locales/hu.json
+++ b/app/javascript/mastodon/locales/hu.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "szerző megjelenítése",
"keyboard_shortcuts.reply": "válaszolás",
"keyboard_shortcuts.search": "kereső kiemelése",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "új tülk megkezdése",
"keyboard_shortcuts.unfocus": "tülk szerkesztés/keresés fókuszpontból való kivétele",
"keyboard_shortcuts.up": "fennebb helyezés a listában",
diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json
index 33e079201..a0442bad4 100644
--- a/app/javascript/mastodon/locales/hy.json
+++ b/app/javascript/mastodon/locales/hy.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "հեղինակին նշելու համար",
"keyboard_shortcuts.reply": "պատասխանելու համար",
"keyboard_shortcuts.search": "որոնման դաշտին սեւեռվելու համար",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "թարմ թութ սկսելու համար",
"keyboard_shortcuts.unfocus": "տեքստի/որոնման տիրույթից ապասեւեռվելու համար",
"keyboard_shortcuts.up": "ցանկով վերեւ շարժվելու համար",
diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json
index 412ffd3a0..2fd922544 100644
--- a/app/javascript/mastodon/locales/id.json
+++ b/app/javascript/mastodon/locales/id.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.search": "untuk fokus mencari",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json
index 9730bf934..ed45ee11e 100644
--- a/app/javascript/mastodon/locales/io.json
+++ b/app/javascript/mastodon/locales/io.json
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json
index 5146d7ca2..c80fc0bd6 100644
--- a/app/javascript/mastodon/locales/it.json
+++ b/app/javascript/mastodon/locales/it.json
@@ -17,8 +17,8 @@
"account.mute": "Silenzia @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.muted": "Muted",
- "account.posts": "Posts",
- "account.posts_with_replies": "Toots with replies",
+ "account.posts": "Toot",
+ "account.posts_with_replies": "Toot con risposte",
"account.report": "Segnala @{name}",
"account.requested": "In attesa di approvazione",
"account.share": "Share @{name}'s profile",
@@ -105,7 +105,7 @@
"empty_column.hashtag": "Non c'è ancora nessun post con questo hashtag.",
"empty_column.home": "Non stai ancora seguendo nessuno. Visita {public} o usa la ricerca per incontrare nuove persone.",
"empty_column.home.public_timeline": "la timeline pubblica",
- "empty_column.list": "There is nothing in this list yet.",
+ "empty_column.list": "Non c'è niente in questo elenco ancora. Quando i membri di questo elenco postano nuovi stati, questi appariranno qui.",
"empty_column.notifications": "Non hai ancora nessuna notifica. Interagisci con altri per iniziare conversazioni.",
"empty_column.public": "Qui non c'è nulla! Scrivi qualcosa pubblicamente, o aggiungi utenti da altri server per riempire questo spazio.",
"follow_request.authorize": "Autorizza",
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 23223cac3..a06bdad24 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -29,8 +29,8 @@
"account.unmute": "@{name}さんのミュートを解除",
"account.unmute_notifications": "@{name}さんからの通知を受け取るようにする",
"account.view_full_profile": "全ての情報を見る",
- "alert.unexpected.message": "不明なエラーが発生しました",
- "alert.unexpected.title": "エラー",
+ "alert.unexpected.message": "不明なエラーが発生しました。",
+ "alert.unexpected.title": "エラー!",
"boost_modal.combo": "次からは{combo}を押せばスキップできます",
"bundle_column_error.body": "コンポーネントの読み込み中に問題が発生しました。",
"bundle_column_error.retry": "再試行",
diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json
index 92367dc95..2a2734673 100644
--- a/app/javascript/mastodon/locales/ko.json
+++ b/app/javascript/mastodon/locales/ko.json
@@ -2,7 +2,7 @@
"account.block": "@{name}을 차단",
"account.block_domain": "{domain} 전체를 숨김",
"account.blocked": "차단 됨",
- "account.direct": "Direct message @{name}",
+ "account.direct": "@{name}으로부터의 다이렉트 메시지",
"account.disclaimer_full": "여기 있는 정보는 유저의 프로파일을 정확히 반영하지 못 할 수도 있습니다.",
"account.domain_blocked": "도메인 숨겨짐",
"account.edit_profile": "프로필 편집",
@@ -12,7 +12,7 @@
"account.follows_you": "날 팔로우합니다",
"account.hide_reblogs": "@{name}의 부스트를 숨기기",
"account.media": "미디어",
- "account.mention": "답장",
+ "account.mention": "@{name}에게 글쓰기",
"account.moved_to": "{name}는 계정을 이동했습니다:",
"account.mute": "@{name} 뮤트",
"account.mute_notifications": "@{name}의 알림을 뮤트",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "멘션",
"keyboard_shortcuts.reply": "답장",
"keyboard_shortcuts.search": "검색창에 포커스",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "새 툿 작성",
"keyboard_shortcuts.unfocus": "작성창에서 포커스 해제",
"keyboard_shortcuts.up": "리스트에서 위로 이동",
diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json
index c18ddbd01..338b7aebc 100644
--- a/app/javascript/mastodon/locales/nl.json
+++ b/app/javascript/mastodon/locales/nl.json
@@ -18,7 +18,7 @@
"account.mute_notifications": "Negeer meldingen van @{name}",
"account.muted": "Genegeerd",
"account.posts": "Toots",
- "account.posts_with_replies": "Toots met reacties",
+ "account.posts_with_replies": "Toots en reacties",
"account.report": "Rapporteer @{name}",
"account.requested": "Wacht op goedkeuring. Klik om het volgverzoek te annuleren",
"account.share": "Profiel van @{name} delen",
@@ -29,8 +29,8 @@
"account.unmute": "@{name} niet meer negeren",
"account.unmute_notifications": "@{name} meldingen niet meer negeren",
"account.view_full_profile": "Volledig profiel tonen",
- "alert.unexpected.message": "An unexpected error occurred.",
- "alert.unexpected.title": "Oops!",
+ "alert.unexpected.message": "Er deed zich een onverwachte fout voor",
+ "alert.unexpected.title": "Oeps!",
"boost_modal.combo": "Je kunt {combo} klikken om dit de volgende keer over te slaan",
"bundle_column_error.body": "Tijdens het laden van dit onderdeel is er iets fout gegaan.",
"bundle_column_error.retry": "Opnieuw proberen",
@@ -41,7 +41,7 @@
"column.blocks": "Geblokkeerde gebruikers",
"column.community": "Lokale tijdlijn",
"column.direct": "Direct messages",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "Verborgen domeinen",
"column.favourites": "Favorieten",
"column.follow_requests": "Volgverzoeken",
"column.home": "Start",
@@ -59,7 +59,7 @@
"column_header.unpin": "Losmaken",
"column_subheading.navigation": "Navigatie",
"column_subheading.settings": "Instellingen",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "compose_form.direct_message_warning": "Deze toot zal alleen zichtbaar zijn voor alle vermelde gebruikers.",
"compose_form.hashtag_warning": "Deze toot valt niet onder een hashtag te bekijken, omdat deze niet op openbare tijdlijnen wordt getoond. Alleen openbare toots kunnen via hashtags gevonden worden.",
"compose_form.lock_disclaimer": "Jouw account is niet {locked}. Iedereen kan jou volgen en toots zien die je alleen aan volgers hebt gericht.",
"compose_form.lock_disclaimer.lock": "besloten",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "om de auteur te vermelden",
"keyboard_shortcuts.reply": "om te reageren",
"keyboard_shortcuts.search": "om het zoekvak te focussen",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "om een nieuwe toot te starten",
"keyboard_shortcuts.unfocus": "om het tekst- en zoekvak te ontfocussen",
"keyboard_shortcuts.up": "om omhoog te bewegen in de lijst",
@@ -157,7 +158,7 @@
"navigation_bar.blocks": "Geblokkeerde gebruikers",
"navigation_bar.community_timeline": "Lokale tijdlijn",
"navigation_bar.direct": "Direct messages",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "Verborgen domeinen",
"navigation_bar.edit_profile": "Profiel bewerken",
"navigation_bar.favourites": "Favorieten",
"navigation_bar.follow_requests": "Volgverzoeken",
@@ -244,7 +245,7 @@
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Deze toot kan niet geboost worden",
"status.delete": "Verwijderen",
- "status.direct": "Direct message @{name}",
+ "status.direct": "Directe toot @{name}",
"status.embed": "Embed",
"status.favourite": "Favoriet",
"status.load_more": "Meer laden",
@@ -275,7 +276,7 @@
"tabs_bar.home": "Start",
"tabs_bar.local_timeline": "Lokaal",
"tabs_bar.notifications": "Meldingen",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "Zoeken",
"ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.",
"upload_area.title": "Hierin slepen om te uploaden",
"upload_button.label": "Media toevoegen",
diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json
index 282a72acb..0ee6d0722 100644
--- a/app/javascript/mastodon/locales/no.json
+++ b/app/javascript/mastodon/locales/no.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "å nevne forfatter",
"keyboard_shortcuts.reply": "for å svare",
"keyboard_shortcuts.search": "å fokusere søk",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "å starte en helt ny tut",
"keyboard_shortcuts.unfocus": "å ufokusere komponerings-/søkefeltet",
"keyboard_shortcuts.up": "å flytte opp i listen",
diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json
index 7170aefb8..66f3fa275 100644
--- a/app/javascript/mastodon/locales/oc.json
+++ b/app/javascript/mastodon/locales/oc.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "mencionar l’autor",
"keyboard_shortcuts.reply": "respondre",
"keyboard_shortcuts.search": "anar a la recèrca",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "començar un estatut tot novèl",
"keyboard_shortcuts.unfocus": "quitar lo camp tèxte/de recèrca",
"keyboard_shortcuts.up": "far montar dins la lista",
diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json
index c604476c7..7013822bf 100644
--- a/app/javascript/mastodon/locales/pt-BR.json
+++ b/app/javascript/mastodon/locales/pt-BR.json
@@ -29,7 +29,7 @@
"account.unmute": "Não silenciar @{name}",
"account.unmute_notifications": "Retirar silêncio das notificações vindas de @{name}",
"account.view_full_profile": "Ver perfil completo",
- "alert.unexpected.message": "An unexpected error occurred.",
+ "alert.unexpected.message": "Um erro inesperado ocorreu.",
"alert.unexpected.title": "Oops!",
"boost_modal.combo": "Você pode pressionar {combo} para ignorar este diálogo na próxima vez",
"bundle_column_error.body": "Algo de errado aconteceu enquanto este componente era carregado.",
@@ -59,7 +59,7 @@
"column_header.unpin": "Desafixar",
"column_subheading.navigation": "Navegação",
"column_subheading.settings": "Configurações",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "compose_form.direct_message_warning": "Este toot só será visível a todos os usuários mencionados.",
"compose_form.hashtag_warning": "Esse toot não será listado em nenhuma hashtag por ser não listado. Somente toots públicos podem ser pesquisados por hashtag.",
"compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.",
"compose_form.lock_disclaimer.lock": "trancada",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "para mencionar o autor",
"keyboard_shortcuts.reply": "para responder",
"keyboard_shortcuts.search": "para focar a pesquisa",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "para compor um novo toot",
"keyboard_shortcuts.unfocus": "para remover o foco da área de composição/pesquisa",
"keyboard_shortcuts.up": "para mover para cima na lista",
@@ -275,7 +276,7 @@
"tabs_bar.home": "Página inicial",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notificações",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "Buscar",
"ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar mídia",
diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json
index 826785aad..ce816dc41 100644
--- a/app/javascript/mastodon/locales/pt.json
+++ b/app/javascript/mastodon/locales/pt.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "para mencionar o autor",
"keyboard_shortcuts.reply": "para responder",
"keyboard_shortcuts.search": "para focar na pesquisa",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "para compor um novo post",
"keyboard_shortcuts.unfocus": "para remover o foco da área de publicação/pesquisa",
"keyboard_shortcuts.up": "para mover para cima na lista",
diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json
index bb3cc1794..8eeebaf73 100644
--- a/app/javascript/mastodon/locales/ru.json
+++ b/app/javascript/mastodon/locales/ru.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "упомянуть автора поста",
"keyboard_shortcuts.reply": "ответить",
"keyboard_shortcuts.search": "перейти к поиску",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "начать писать новый пост",
"keyboard_shortcuts.unfocus": "убрать фокус с поля ввода/поиска",
"keyboard_shortcuts.up": "вверх по списку",
diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json
index 58274fd2d..8b19cac6f 100644
--- a/app/javascript/mastodon/locales/sk.json
+++ b/app/javascript/mastodon/locales/sk.json
@@ -2,7 +2,7 @@
"account.block": "Blokovať @{name}",
"account.block_domain": "Ukryť všetko z {domain}",
"account.blocked": "Blokovaný/á",
- "account.direct": "Direct message @{name}",
+ "account.direct": "Súkromná správa pre @{name}",
"account.disclaimer_full": "Inofrmácie nižšie nemusia byť úplným odrazom uživateľovho účtu.",
"account.domain_blocked": "Doména ukrytá",
"account.edit_profile": "Upraviť profil",
@@ -29,7 +29,7 @@
"account.unmute": "Prestať ignorovať @{name}",
"account.unmute_notifications": "Odtĺmiť notifikácie od @{name}",
"account.view_full_profile": "Pozri celý profil",
- "alert.unexpected.message": "An unexpected error occurred.",
+ "alert.unexpected.message": "Vyskytla sa neočakávaná chyba.",
"alert.unexpected.title": "Oops!",
"boost_modal.combo": "Nabudúce môžete kliknúť {combo} aby ste preskočili",
"bundle_column_error.body": "Nastala chyba pri načítaní tohto komponentu.",
@@ -41,7 +41,7 @@
"column.blocks": "Blokovaní užívatelia",
"column.community": "Lokálna časová os",
"column.direct": "Direct messages",
- "column.domain_blocks": "Hidden domains",
+ "column.domain_blocks": "Skryté domény",
"column.favourites": "Obľúbené",
"column.follow_requests": "Žiadosti o sledovanie",
"column.home": "Domov",
@@ -59,7 +59,7 @@
"column_header.unpin": "Odopnúť",
"column_subheading.navigation": "Navigácia",
"column_subheading.settings": "Nastavenia",
- "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.",
+ "compose_form.direct_message_warning": "Tento príspevok bude videný výhradne iba spomenutými užívateľmi.",
"compose_form.hashtag_warning": "Tento toot nebude zobrazený pod žiadným haštagom lebo nieje listovaný. Iba verejné tooty môžu byť nájdené podľa haštagu.",
"compose_form.lock_disclaimer": "Váš účet nie je zamknutý. Ktokoľvek ťa môže nasledovať a vidieť tvoje správy pre sledujúcich.",
"compose_form.lock_disclaimer.lock": "zamknutý",
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "spomenúť autora",
"keyboard_shortcuts.reply": "odpovedať",
"keyboard_shortcuts.search": "zamerať sa na vyhľadávanie",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "začať úplne novú hlášku",
"keyboard_shortcuts.unfocus": "nesústrediť sa na písaciu plochu, alebo hľadanie",
"keyboard_shortcuts.up": "posunúť sa vyššie v zozname",
@@ -157,7 +158,7 @@
"navigation_bar.blocks": "Blokovaní užívatelia",
"navigation_bar.community_timeline": "Lokálna časová os",
"navigation_bar.direct": "Direct messages",
- "navigation_bar.domain_blocks": "Hidden domains",
+ "navigation_bar.domain_blocks": "Skryté domény",
"navigation_bar.edit_profile": "Upraviť profil",
"navigation_bar.favourites": "Obľúbené",
"navigation_bar.follow_requests": "Žiadosti o sledovanie",
@@ -244,7 +245,7 @@
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
"status.delete": "Zmazať",
- "status.direct": "Direct message @{name}",
+ "status.direct": "Súkromná správa @{name}",
"status.embed": "Vložiť",
"status.favourite": "Páči sa mi",
"status.load_more": "Zobraz viac",
@@ -275,7 +276,7 @@
"tabs_bar.home": "Domov",
"tabs_bar.local_timeline": "Lokálna",
"tabs_bar.notifications": "Notifikácie",
- "tabs_bar.search": "Search",
+ "tabs_bar.search": "Hľadaj",
"ui.beforeunload": "Čo máte rozpísané sa stratí, ak opustíte Mastodon.",
"upload_area.title": "Ťahaj a pusti pre nahratie",
"upload_button.label": "Pridať médiá",
diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json
index e4d07edd1..b1ea0d179 100644
--- a/app/javascript/mastodon/locales/sr-Latn.json
+++ b/app/javascript/mastodon/locales/sr-Latn.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "da pomenete autora",
"keyboard_shortcuts.reply": "da odgovorite",
"keyboard_shortcuts.search": "da se prebacite na pretragu",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "da započnete skroz novi tut",
"keyboard_shortcuts.unfocus": "da ne budete više na pretrazi/pravljenju novog tuta",
"keyboard_shortcuts.up": "da se pomerite na gore u listi",
diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json
index 60c781e9d..aa978675f 100644
--- a/app/javascript/mastodon/locales/sr.json
+++ b/app/javascript/mastodon/locales/sr.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "да поменете аутора",
"keyboard_shortcuts.reply": "да одговорите",
"keyboard_shortcuts.search": "да се пребаците на претрагу",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "да започнете скроз нови тут",
"keyboard_shortcuts.unfocus": "да не будете више на претрази/прављењу новог тута",
"keyboard_shortcuts.up": "да се померите на горе у листи",
diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json
index 8fa6992f1..7db4d57a7 100644
--- a/app/javascript/mastodon/locales/sv.json
+++ b/app/javascript/mastodon/locales/sv.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "att nämna författaren",
"keyboard_shortcuts.reply": "att svara",
"keyboard_shortcuts.search": "att fokusera sökfältet",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "att börja en helt ny toot",
"keyboard_shortcuts.unfocus": "att avfokusera komponera text fält / sökfält",
"keyboard_shortcuts.up": "att flytta upp i listan",
diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json
index 3b91c0d2c..82b44fe30 100644
--- a/app/javascript/mastodon/locales/th.json
+++ b/app/javascript/mastodon/locales/th.json
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json
index cdf6f46a3..056fbfe8f 100644
--- a/app/javascript/mastodon/locales/tr.json
+++ b/app/javascript/mastodon/locales/tr.json
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json
index 261e5795e..1a7b58789 100644
--- a/app/javascript/mastodon/locales/uk.json
+++ b/app/javascript/mastodon/locales/uk.json
@@ -135,6 +135,7 @@
"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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json
index aba0bde83..a3a4de0af 100644
--- a/app/javascript/mastodon/locales/zh-CN.json
+++ b/app/javascript/mastodon/locales/zh-CN.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "提及嘟文作者",
"keyboard_shortcuts.reply": "回复嘟文",
"keyboard_shortcuts.search": "选择搜索框",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "发送新嘟文",
"keyboard_shortcuts.unfocus": "取消输入",
"keyboard_shortcuts.up": "在列表中让光标上移",
diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json
index b5ebd20fc..7719e08a6 100644
--- a/app/javascript/mastodon/locales/zh-HK.json
+++ b/app/javascript/mastodon/locales/zh-HK.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "提及作者",
"keyboard_shortcuts.reply": "回覆",
"keyboard_shortcuts.search": "把標示移動到搜索",
+ "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "新的推文",
"keyboard_shortcuts.unfocus": "把標示移離文字輸入和搜索",
"keyboard_shortcuts.up": "在列表往上移動",
diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json
index 28d634600..84ff25e03 100644
--- a/app/javascript/mastodon/locales/zh-TW.json
+++ b/app/javascript/mastodon/locales/zh-TW.json
@@ -135,6 +135,7 @@
"keyboard_shortcuts.mention": "到提到的作者",
"keyboard_shortcuts.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.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
diff --git a/config/locales/activerecord.eu.yml b/config/locales/activerecord.eu.yml
new file mode 100644
index 000000000..7b0ebe0b0
--- /dev/null
+++ b/config/locales/activerecord.eu.yml
@@ -0,0 +1,9 @@
+---
+eu:
+ activerecord:
+ errors:
+ models:
+ account:
+ attributes:
+ username:
+ invalid: letrak, zenbakiak eta gidoi baxuak besterik ez
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index c9173cd5e..9e927f74f 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -4,6 +4,7 @@ ca:
about_hashtag_html: Aquests són toots públics etiquetats amb #%{hashtag}. Pots interactuar amb ells si tens un compte a qualsevol lloc del fediverse.
about_mastodon_html: Mastodon és una xarxa social basada en protocols web oberts i en programari lliure i de codi obert. Està descentralitzat com el correu electrònic.
about_this: Quant a
+ administered_by: 'Administrat per:'
closed_registrations: Actualment, el registre està tancat en aquesta instància. Malgrat això! Pots trobar una altra instància per fer-te un compte i obtenir accés a la mateixa xarxa des d'allà.
contact: Contacte
contact_missing: No configurat
@@ -60,7 +61,15 @@ ca:
destroyed_msg: Nota de moderació destruïda amb èxit!
accounts:
are_you_sure: N'estàs segur?
+ avatar: Avatar
by_domain: Domini
+ change_email:
+ changed_msg: El correu electrònic del compte s'ha canviat correctament!
+ current_email: Correu electrònic actual
+ label: Canviar l'adreça de correu
+ new_email: Nou correu
+ submit: Canviar adreça de correu
+ title: Canviar adreça de correu de %{username}
confirm: Confirma
confirmed: Confirmat
demote: Degrada
@@ -108,6 +117,7 @@ ca:
public: Públic
push_subscription_expires: La subscripció PuSH expira
redownload: Actualitza l'avatar
+ remove_avatar: Eliminar avatar
reset: Reinicialitza
reset_password: Restableix la contrasenya
resubscribe: Torna a subscriure
@@ -128,6 +138,7 @@ ca:
statuses: Estats
subscribe: Subscriu
title: Comptes
+ unconfirmed_email: Correu electrònic sense confirmar
undo_silenced: Deixa de silenciar
undo_suspension: Desfés la suspensió
unsubscribe: Cancel·la la subscripció
@@ -135,6 +146,8 @@ ca:
web: Web
action_logs:
actions:
+ assigned_to_self_report: "%{name} han assignat l'informe %{target} a ells mateixos"
+ change_email_user: "%{name} ha canviat l'adreça de correu electrònic del usuari %{target}"
confirm_user: "%{name} ha confirmat l'adreça de correu electrònic de l'usuari %{target}"
create_custom_emoji: "%{name} ha pujat un nou emoji %{target}"
create_domain_block: "%{name} ha blocat el domini %{target}"
@@ -150,10 +163,13 @@ ca:
enable_user: "%{name} ha activat l'accés per a l'usuari %{target}"
memorialize_account: "%{name} ha convertit el compte %{target} en una pàgina de memorial"
promote_user: "%{name} ha promogut l'usuari %{target}"
+ remove_avatar_user: "%{name} ha eliminat l'avatar de %{target}"
+ reopen_report: "%{name} ha reobert l'informe %{target}"
reset_password_user: "%{name} ha restablert la contrasenya de l'usuari %{target}"
- resolve_report: "%{name} ha descartat l'informe %{target}"
+ resolve_report: "%{name} ha resolt l'informe %{target}"
silence_account: "%{name} ha silenciat el compte de %{target}"
suspend_account: "%{name} ha suspès el compte de %{target}"
+ unassigned_report: "%{name} ha des-assignat l'informe %{target}"
unsilence_account: "%{name} ha silenciat el compte de %{target}"
unsuspend_account: "%{name} ha llevat la suspensió del compte de %{target}"
update_custom_emoji: "%{name} ha actualitzat l'emoji %{target}"
@@ -239,28 +255,48 @@ ca:
expired: Caducat
title: Filtre
title: Convida
+ report_notes:
+ created_msg: La nota del informe s'ha creat correctament!
+ destroyed_msg: La nota del informe s'ha esborrat correctament!
reports:
+ account:
+ note: nota
+ report: informe
action_taken_by: Mesures adoptades per
are_you_sure: N'estàs segur?
+ assign_to_self: Assignar-me
+ assigned: Assignar Moderador
comment:
none: Cap
+ created_at: Reportat
delete: Suprimeix
id: ID
mark_as_resolved: Marca com a resolt
+ mark_as_unresolved: Marcar sense resoldre
+ notes:
+ create: Afegir nota
+ create_and_resolve: Resoldre amb Nota
+ create_and_unresolve: Reobrir amb Nota
+ delete: Esborrar
+ placeholder: Descriu les accions que s'han pres o qualsevol altra actualització d'aquest informe…
nsfw:
'false': Mostra els fitxers multimèdia adjunts
'true': Amaga els fitxers multimèdia adjunts
+ reopen: Reobrir Informe
report: 'Informe #%{id}'
report_contents: Contingut
reported_account: Compte reportat
reported_by: Reportat per
resolved: Resolt
+ resolved_msg: Informe resolt amb èxit!
silence_account: Silencia el compte
status: Estat
suspend_account: Suspèn el compte
target: Objectiu
title: Informes
+ unassign: Treure assignació
unresolved: No resolt
+ updated_at: Actualitzat
view: Visualització
settings:
activity_api_enabled:
@@ -381,6 +417,7 @@ ca:
security: Seguretat
set_new_password: Estableix una contrasenya nova
authorize_follow:
+ already_following: Ja estàs seguint aquest compte
error: Malauradament, ha ocorregut un error cercant el compte remot
follow: Segueix
follow_request: 'Has enviat una sol·licitud de seguiment a:'
@@ -473,6 +510,7 @@ ca:
'21600': 6 hores
'3600': 1 hora
'43200': 12 hores
+ '604800': 1 setmana
'86400': 1 dia
expires_in_prompt: Mai
generate: Genera
@@ -576,6 +614,10 @@ ca:
missing_resource: No s'ha pogut trobar la URL de redirecció necessaria per al compte
proceed: Comença a seguir
prompt: 'Seguiràs a:'
+ remote_unfollow:
+ error: Error
+ title: Títol
+ unfollowed: Sense seguir
sessions:
activity: Última activitat
browser: Navegador
@@ -664,6 +706,83 @@ ca:
reblogged: ha impulsat
sensitive_content: Contingut sensible
terms:
+ body_html: |
+
Privacy Policy
+
Quina informació recollim?
+
+
+
Informació bàsica del compte: Si et registres en aquest servidor, se´t pot demanar que introdueixis un nom d'usuari, una adreça de correu electrònic i una contrasenya. També pots introduir informació de perfil addicional, com ara un nom de visualització i una biografia, i carregar una imatge de perfil i de capçalera. El nom d'usuari, el nom de visualització, la biografia, la imatge de perfil i la imatge de capçalera sempre apareixen públicament.
+
Publicacions, seguiment i altra informació pública: La llista de persones que segueixes s'enumeren públicament i el mateix passa amb els teus seguidors. Quan envies un missatge, la data i l'hora s'emmagatzemen, així com l'aplicació que va enviar el missatge. Els missatges poden contenir multimèdia, com ara imatges i vídeos. Els toots públics i no llistats estan disponibles públicament. En quan tinguis un toot en el teu perfil, aquest també és informació pública. Les teves entrades es lliuren als teus seguidors que en alguns casos significa que es lliuren a diferents servidors i s'hi emmagatzemen còpies. Quan suprimeixes publicacions, també es lliurarà als vostres seguidors. L'acció d'impulsar o marcar com a favorit una publicació sempre és pública.
+
Toots directes i per a només seguidors: Totes les publicacions s'emmagatzemen i processen al servidor. Els toots per a només seguidors només es lliuren als teus seguidors i als usuaris que s'esmenten en ells i els toots directes només es lliuren als usuaris esmentats. En alguns casos, significa que es lliuren a diferents servidors i s'hi emmagatzemen còpies. Fem un esforç de bona fe per limitar l'accés a aquestes publicacions només a les persones autoritzades, però és possible que altres servidors no ho facin. Per tant, és important revisar els servidors als quals pertanyen els teus seguidors. Pots canviar d'opció per aprovar i rebutjar els nous seguidors manualment a la configuració. Tingues en compte que els operadors del servidor i qualsevol servidor receptor poden visualitzar aquests missatges i els destinataris poden fer una captura de pantalla, copiar-los o tornar-los a compartir. No comparteixis cap informació perillosa a Mastodon.
+
IPs i altres metadades: Quan inicies sessió registrem l'adreça IP en què has iniciat la sessió, així com el nom de l'aplicació o navegador. Totes les sessions registrades estan disponibles per a la teva revisió i revocació a la configuració. L'última adreça IP utilitzada s'emmagatzema durant un màxim de 12 mesos. També podrem conservar els registres del servidor que inclouen l'adreça IP de cada sol·licitud al nostre servidor.
+
+
+
+
+
Per a què utilitzem la teva informació?
+
+
Qualsevol de la informació que recopilem de tu es pot utilitzar de la manera següent:
+
+
+
Per proporcionar la funcionalitat bàsica de Mastodon. Només pots interactuar amb el contingut d'altres persones i publicar el teu propi contingut quan hàgis iniciat la sessió. Per exemple, pots seguir altres persones per veure les publicacions combinades a la teva pròpia línia de temps personalitzada.
+
Per ajudar a la moderació de la comunitat, per exemple comparar la teva adreça IP amb altres conegudes per determinar l'evasió de la prohibició o altres infraccions.
+
L'adreça electrònica que proporciones pot utilitzar-se per enviar-te informació, notificacions sobre altres persones que interactuen amb el teu contingut o t'envien missatges, i per respondre a les consultes i / o altres sol·licituds o preguntes.
+
+
+
+
+
Com protegim la teva informació
+
+
Implementem diverses mesures per mantenir la seguretat de la teva informació personal quan introdueixes, envies o accedeixes a la teva informació personal. Entre altres coses, la sessió del teu navegador així com el trànsit entre les teves aplicacions i l'API estan protegides amb SSL i la teva contrasenya es codifica utilitzant un algoritme de direcció única. Pots habilitar l'autenticació de dos factors per a garantir l'accés segur al teu compte.
+
+
+
+
Quina és la nostra política de retenció de dades?
+
+
Farem un esforç de bona fe per:
+
+
+
Conservar els registres del servidor que continguin l'adreça IP de totes les sol·licituds a aquest servidor, tenint em compte que aquests registres es mantenen no més de 90 dies.
+
Conservar les adreces IP associades als usuaris registrats no més de 12 mesos.
+
+
+
Pots sol·licitar i descarregar un arxiu del teu contingut incloses les publicacions, els fitxers adjunts multimèdia, la imatge de perfil i la imatge de capçalera.
+
+
Pots eliminar el compte de forma irreversible en qualsevol moment.
+
+
+
+
Utilitzem cookies?
+
+
Sí. Les cookies són petits fitxers que un lloc o el proveïdor de serveis transfereix al disc dur del teu ordinador a través del navegador web (si ho permet). Aquestes galetes permeten al lloc reconèixer el teu navegador i, si teniu un compte registrat, associar-lo al teu compte registrat.
+
+
Utilitzem cookies per entendre i guardar les teves preferències per a futures visites.
+
+
+
+
Revelem informació a terceres parts?
+
+
No venem, comercialitzem ni transmetem a tercers la teva informació d'identificació personal. Això no inclou tercers de confiança que ens ajuden a operar el nostre lloc, a dur a terme el nostre negoci o a servir-te, sempre que aquestes parts acceptin mantenir confidencial aquesta informació. També podem publicar la teva informació quan creiem que l'alliberament és apropiat per complir amb la llei, fer complir les polítiques del nostre lloc o protegir els nostres drets o altres drets, propietat o seguretat.
+
+
Els altres servidors de la teva xarxa poden descarregar contingut públic. Els teus toots públics i per a només seguidors es lliuren als servidors on resideixen els teus seguidors i els missatges directes s'envien als servidors dels destinataris, sempre que aquests seguidors o destinataris resideixin en un servidor diferent d'això.
+
+
Quan autoritzes una aplicació a utilitzar el teu compte, segons l'abast dels permisos que aprovis, pot accedir a la teva informació de perfil pública, a la teva llista de seguits, als teus seguidors, a les teves llistes, a totes les teves publicacions i als teus favorits. Les aplicacions mai no poden accedir a la teva adreça de correu electrònic o contrasenya.
+
+
+
+
Compliment de la Llei de protecció de la privacitat en línia dels nens
+
+
El nostre lloc, productes i serveis estan dirigits a persones que tenen almenys 13 anys. Si aquest servidor es troba als EUA, i teniu menys de 13 anys, segons els requisits de COPPA (Children's Online Privacy Protection Act) no utilitzis aquest lloc.
+
+
+
+
Canvis a la nostra política de privacitat
+
+
Si decidim canviar la nostra política de privadesa, publicarem aquests canvis en aquesta pàgina.
+
+
Aquest document és CC-BY-SA. Actualitzat per darrera vegada el 7 de Març del 2018.
title: "%{instance} Condicions del servei i política de privadesa"
themes:
default: Mastodont
diff --git a/config/locales/devise.eu.yml b/config/locales/devise.eu.yml
new file mode 100644
index 000000000..215b72e52
--- /dev/null
+++ b/config/locales/devise.eu.yml
@@ -0,0 +1,5 @@
+---
+eu:
+ devise:
+ failure:
+ already_authenticated: Saioa hasi duzu jada.
diff --git a/config/locales/devise.it.yml b/config/locales/devise.it.yml
index e1ba7bb22..0c5d8963c 100644
--- a/config/locales/devise.it.yml
+++ b/config/locales/devise.it.yml
@@ -17,11 +17,32 @@ it:
unconfirmed: Devi confermare il tuo indirizzo email per continuare.
mailer:
confirmation_instructions:
+ action: Verifica indirizzo email
+ explanation: Hai creato un account su %{host} con questo indirizzo email. Sei lonatno solo un clic dall'attivarlo. Se non sei stato tu, per favore ignora questa email.
+ extra_html: Per favore controllale regole dell'istanza e i nostri termini di servizio.
subject: 'Mastodon: Istruzioni di conferma per %{instance}'
+ title: Verifica indirizzo email
+ email_changed:
+ explanation: 'L''indirizzo email del tuo account sta per essere cambiato in:'
+ extra: Se non hai cambiato la tua email, è probabile che qualcuno abbia accesso al tuo account. Cambia immediatamente la tua password e contatta l'amministratore dell'istanza se sei bloccato fuori dal tuo account.
+ subject: 'Mastodon: Email cambiata'
+ title: Nuovo indirizzo email
password_change:
+ explanation: La password del tuo account è stata cambiata.
+ extra: Se non hai cambiato la password, è probabile che qualcuno abbia accesso al tuo account. Cambia immediatamente la tua password e contatta l'amministratore dell'istanza se sei bloccato fuori dal tuo account.
subject: 'Mastodon: Password modificata'
+ title: Password cambiata
+ reconfirmation_instructions:
+ explanation: Conferma il nuovo indirizzo per cambiare la tua email.
+ extra: Se questo cambiamento non è stato chiesto da te, ignora questa email. L'indirizzo email per l'account Mastodon non verrà cambiato finché non accedi dal link qui sopra.
+ subject: 'Mastodon: Email di conferma per %{instance}'
+ title: Verifica indirizzo email
reset_password_instructions:
+ action: Cambia password
+ explanation: Hai richiesto una nuova password per il tuo account.
+ extra: Se questo cambiamento non è stato chiesto da te, ignora questa email. La tua password non verrà cambiata finché non accedi tramite il link qui sopra e ne crei una nuova.
subject: 'Mastodon: Istruzioni per il reset della password'
+ title: Ripristino password
unlock_instructions:
subject: 'Mastodon: Istruzioni di sblocco'
omniauth_callbacks:
diff --git a/config/locales/doorkeeper.eu.yml b/config/locales/doorkeeper.eu.yml
new file mode 100644
index 000000000..a51b1dc8b
--- /dev/null
+++ b/config/locales/doorkeeper.eu.yml
@@ -0,0 +1,6 @@
+---
+eu:
+ activerecord:
+ attributes:
+ doorkeeper/application:
+ name: Aplikazioaren izena
diff --git a/config/locales/doorkeeper.it.yml b/config/locales/doorkeeper.it.yml
index e5a2d3f6e..50b2c9780 100644
--- a/config/locales/doorkeeper.it.yml
+++ b/config/locales/doorkeeper.it.yml
@@ -3,8 +3,10 @@ it:
activerecord:
attributes:
doorkeeper/application:
- name: Nome
+ name: Nome applicazione
redirect_uri: URI di reindirizzamento
+ scopes: Scopi
+ website: Sito web applicazione
errors:
models:
doorkeeper/application:
@@ -33,9 +35,13 @@ it:
redirect_uri: Usa una riga per URI
scopes: Dividi gli scopes con spazi. Lascia vuoto per utilizzare gli scopes di default.
index:
+ application: Applicazione
callback_url: Callback URL
+ delete: Elimina
name: Nome
new: Nuova applicazione
+ scopes: Scopes
+ show: Mostra
title: Le tue applicazioni
new:
title: Nuova applicazione
@@ -43,7 +49,7 @@ it:
actions: Azioni
application_id: Id applicazione
callback_urls: Callback urls
- scopes: Scopes
+ scopes: Scopi
secret: Secret
title: 'Applicazione: %{name}'
authorizations:
@@ -57,7 +63,7 @@ it:
prompt: L'applicazione %{client_name} richiede l'accesso al tuo account
title: Autorizzazione richiesta
show:
- title: Copy this authorization code and paste it to the application.
+ title: Copia questo codice di autorizzazione e incollalo nell'applicazione.
authorized_applications:
buttons:
revoke: Disabilita
@@ -67,7 +73,7 @@ it:
application: Applicazione
created_at: Autorizzato
date_format: "%d-%m-%Y %H:%M:%S"
- scopes: Scopes
+ scopes: Scopi
title: Applicazioni autorizzate
errors:
messages:
@@ -104,7 +110,7 @@ it:
admin:
nav:
applications: Applicazioni
- oauth2_provider: OAuth2 Provider
+ oauth2_provider: Provider OAuth2
application:
title: Autorizzazione OAuth richiesta
scopes:
diff --git a/config/locales/eu.yml b/config/locales/eu.yml
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/config/locales/eu.yml
@@ -0,0 +1 @@
+{}
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index ebe579354..fa96d9d05 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -4,6 +4,7 @@ fr:
about_hashtag_html: Figurent ci-dessous les pouets tagués avec #%{hashtag}. Vous pouvez interagir avec eux si vous avez un compte n’importe où dans le Fediverse.
about_mastodon_html: Mastodon est un réseau social utilisant des formats ouverts et des logiciels libres. Comme le courriel, il est décentralisé.
about_this: À propos
+ administered_by: 'Administré par :'
closed_registrations: Les inscriptions sont actuellement fermées sur cette instance. Cependant, vous pouvez trouver une autre instance sur laquelle vous créer un compte et à partir de laquelle vous pourrez accéder au même réseau.
contact: Contact
contact_missing: Manquant
@@ -60,7 +61,15 @@ fr:
destroyed_msg: Note de modération supprimée avec succès !
accounts:
are_you_sure: Êtes-vous certain⋅e ?
+ avatar: Avatar
by_domain: Domaine
+ change_email:
+ changed_msg: Courriel du compte modifié avec succès !
+ current_email: Courriel actuel
+ label: Modifier le courriel
+ new_email: Nouveau courriel
+ submit: Modifier le courriel
+ title: Modifier le courriel pour %{username}
confirm: Confirmer
confirmed: Confirmé
demote: Rétrograder
@@ -108,6 +117,7 @@ fr:
public: Publique
push_subscription_expires: Expiration de l’abonnement PuSH
redownload: Rafraîchir les avatars
+ remove_avatar: Supprimer l'avatar
reset: Réinitialiser
reset_password: Réinitialiser le mot de passe
resubscribe: Se réabonner
@@ -128,6 +138,7 @@ fr:
statuses: Statuts
subscribe: S’abonner
title: Comptes
+ unconfirmed_email: Courriel non-confirmé
undo_silenced: Démasquer
undo_suspension: Annuler la suspension
unsubscribe: Se désabonner
@@ -135,6 +146,8 @@ fr:
web: Web
action_logs:
actions:
+ assigned_to_self_report: "%{name} s'est assigné le signalement de %{target} à eux-même"
+ change_email_user: "%{name} a modifié l'adresse de courriel de l'utilisateur %{target}"
confirm_user: "%{name} adresse courriel confirmée de l'utilisateur %{target}"
create_custom_emoji: "%{name} a importé de nouveaux emoji %{target}"
create_domain_block: "%{name} a bloqué le domaine %{target}"
@@ -150,10 +163,13 @@ fr:
enable_user: "%{name} a activé le login pour l'utilisateur %{target}"
memorialize_account: "%{name} a transformé le compte de %{target} en une page de mémorial"
promote_user: "%{name} a promu l'utilisateur %{target}"
+ remove_avatar_user: "%{name} a supprimé l'avatar de %{target}'s"
+ reopen_report: "%{name} a ré-ouvert le signalement %{target}"
reset_password_user: "%{name} a réinitialisé le mot de passe de %{target}"
- resolve_report: "%{name} n'a pas pris en compte la dénonciation de %{target}"
+ resolve_report: "%{name} a résolu la dénonciation de %{target}"
silence_account: "%{name} a mis le compte %{target} en mode silence"
suspend_account: "%{name} a suspendu le compte %{target}"
+ unassigned_report: "%{name} a dés-assigné le signalement %{target}"
unsilence_account: "%{name} a mis fin au mode silence de %{target}"
unsuspend_account: "%{name} a réactivé le compte de %{target}"
update_custom_emoji: "%{name} a mis à jour l'emoji %{target}"
@@ -239,28 +255,48 @@ fr:
expired: Expiré
title: Filtre
title: Invitations
+ report_notes:
+ created_msg: Note de signalement créée avec succès !
+ destroyed_msg: Note de signalement effacée avec succès !
reports:
+ account:
+ note: note
+ report: signaler
action_taken_by: Intervention de
are_you_sure: Êtes vous certain⋅e ?
+ assign_to_self: Me l'assigner
+ assigned: Modérateur assigné
comment:
none: Aucun
+ created_at: Signalé
delete: Supprimer
id: ID
mark_as_resolved: Marquer comme résolu
+ mark_as_unresolved: Marquer comme non-résolu
+ notes:
+ create: Ajouter une note
+ create_and_resolve: Résoudre avec une note
+ create_and_unresolve: Ré-ouvrir avec une note
+ delete: Effacer
+ placeholder: Décrivez quelles actions ont été prises, ou toute autre mise à jour de ce signalement…
nsfw:
'false': Ré-afficher les médias
'true': Masquer les médias
+ reopen: Ré-ouvrir le signalement
report: 'Signalement #%{id}'
report_contents: Contenu
reported_account: Compte signalé
reported_by: Signalé par
resolved: Résolus
+ resolved_msg: Signalement résolu avec succès !
silence_account: Masquer le compte
status: Statut
suspend_account: Suspendre le compte
target: Cible
title: Signalements
+ unassign: Dés-assigner
unresolved: Non résolus
+ updated_at: Mis à jour
view: Voir
settings:
activity_api_enabled:
@@ -381,6 +417,7 @@ fr:
security: Sécurité
set_new_password: Définir le nouveau mot de passe
authorize_follow:
+ already_following: Vous suivez déjà ce compte
error: Malheureusement, il y a eu une erreur en cherchant les détails du compte distant
follow: Suivre
follow_request: 'Vous avez demandé à suivre :'
@@ -473,6 +510,7 @@ fr:
'21600': 6 heures
'3600': 1 heure
'43200': 12 heures
+ '604800': 1 semaine
'86400': 1 jour
expires_in_prompt: Jamais
generate: Générer
@@ -576,6 +614,10 @@ fr:
missing_resource: L’URL de redirection n’a pas pu être trouvée
proceed: Continuez pour suivre
prompt: 'Vous allez suivre :'
+ remote_unfollow:
+ error: Erreur
+ title: Titre
+ unfollowed: Non-suivi
sessions:
activity: Dernière activité
browser: Navigateur
@@ -641,6 +683,7 @@ fr:
video:
one: "%{count} vidéo"
other: "%{count} vidéos"
+ content_warning: 'Attention au contenu : %{warning}'
open_in_web: Ouvrir sur le web
over_character_limit: limite de caractères dépassée de %{max} caractères
pin_errors:
diff --git a/config/locales/gl.yml b/config/locales/gl.yml
index 89de27a9a..3f936c0ea 100644
--- a/config/locales/gl.yml
+++ b/config/locales/gl.yml
@@ -4,6 +4,7 @@ gl:
about_hashtag_html: Estas son mensaxes públicas etiquetadas con #%{hashtag}. Pode interactuar con elas si ten unha conta nalgures do fediverso.
about_mastodon_html: Mastodon é unha rede social que se basea en protocolos web abertos e libres, software de código aberto. É descentralizada como o correo electrónico.
about_this: Sobre
+ administered_by: 'Administrada por:'
closed_registrations: O rexistro en esta instancia está pechado en este intre. Porén! Pode atopar unha instancia diferente para obter unha conta e ter acceso exactamente a misma rede desde alí.
contact: Contacto
contact_missing: Non establecido
@@ -60,7 +61,15 @@ gl:
destroyed_msg: Nota a moderación destruída con éxito!
accounts:
are_you_sure: Está segura?
+ avatar: Avatar
by_domain: Dominio
+ change_email:
+ changed_msg: Cambiouse correctamente o correo-e da conta!
+ current_email: Correo-e actual
+ label: Cambiar correo-e
+ new_email: Novo correo-e
+ submit: Cambiar correo-e
+ title: Cambiar o correo-e de %{username}
confirm: Confirmar
confirmed: Confirmado
demote: Degradar
@@ -108,6 +117,7 @@ gl:
public: Público
push_subscription_expires: A suscrición PuSH caduca
redownload: Actualizar avatar
+ remove_avatar: Eliminar avatar
reset: Restablecer
reset_password: Restablecer contrasinal
resubscribe: Voltar a suscribir
@@ -128,6 +138,7 @@ gl:
statuses: Estados
subscribe: Subscribir
title: Contas
+ unconfirmed_email: Correo-e non confirmado
undo_silenced: Desfacer acalar
undo_suspension: Desfacer suspensión
unsubscribe: Non subscribir
@@ -135,6 +146,8 @@ gl:
web: Web
action_logs:
actions:
+ assigned_to_self_report: "%{name} asignou o informe %{target} a ela misma"
+ change_email_user: "%{name} cambiou o enderezo de correo-e da usuaria %{target}"
confirm_user: "%{name} comfirmou o enderezo de correo da usuaria %{target}"
create_custom_emoji: "%{name} subeu un novo emoji %{target}"
create_domain_block: "%{name} bloqueou o dominio %{target}"
@@ -150,10 +163,13 @@ gl:
enable_user: "%{name} habilitou a conexión para a usuaria %{target}"
memorialize_account: "%{name} converteu a conta de %{target} nunha páxina para a lembranza"
promote_user: "%{name} promoveu a usuaria %{target}"
+ remove_avatar_user: "%{name} eliminou o avatar de %{target}"
+ reopen_report: "%{name} voltou abrir informe %{target}"
reset_password_user: "%{name} restableceu o contrasinal da usuaria %{target}"
- resolve_report: "%{name} rexeitou o informe %{target}"
+ resolve_report: "%{name} solucionou o informe %{target}"
silence_account: "%{name} acalou a conta de %{target}"
suspend_account: "%{name} suspendeu a conta de %{target}"
+ unassigned_report: "%{name} non asignou informe %{target}"
unsilence_account: "%{name} deulle voz a conta de %{target}"
unsuspend_account: "%{name} activou a conta de %{target}"
update_custom_emoji: "%{name} actualizou emoji %{target}"
@@ -239,28 +255,48 @@ gl:
expired: Cadudado
title: Filtro
title: Convida
+ report_notes:
+ created_msg: Creouse correctamente a nota do informe!
+ destroyed_msg: Nota do informe eliminouse con éxito!
reports:
+ account:
+ note: nota
+ report: informe
action_taken_by: Acción tomada por
are_you_sure: Está segura?
+ assign_to_self: Asignarmo
+ assigned: Asignado ao Moderador
comment:
none: Nada
+ created_at: Reportado
delete: Eliminar
id: ID
mark_as_resolved: Marcar como resolto
+ mark_as_unresolved: Marcar como non resolto
+ notes:
+ create: Engadir nota
+ create_and_resolve: Resolver con nota
+ create_and_unresolve: Votar a abrir con Nota
+ delete: Eliminar
+ placeholder: Describir qué decisións foron tomadas, ou calquer actualización a este informe…
nsfw:
'false': Non agochar anexos de medios
'true': Agochar anexos de medios
+ reopen: Voltar a abrir o informe
report: 'Informe #%{id}'
report_contents: Contidos
reported_account: Conta reportada
reported_by: Reportada por
resolved: Resolto
+ resolved_msg: Resolveuse con éxito o informe!
silence_account: Acalar conta
status: Estado
suspend_account: Suspender conta
target: Obxetivo
title: Informes
+ unassign: Non asignar
unresolved: Non resolto
+ updated_at: Actualizado
view: Vista
settings:
activity_api_enabled:
@@ -381,6 +417,7 @@ gl:
security: Seguridade
set_new_password: Establecer novo contrasinal
authorize_follow:
+ already_following: Xa está a seguir esta conta
error: Desgraciadamente, algo fallou ao buscar a conta remota
follow: Seguir
follow_request: 'Enviou unha petición de seguimento a:'
@@ -473,6 +510,7 @@ gl:
'21600': 6 horas
'3600': 1 hora
'43200': 12 horas
+ '604800': 1 semana
'86400': 1 día
expires_in_prompt: Nunca
generate: Xerar
@@ -576,6 +614,10 @@ gl:
missing_resource: Non se puido atopar o URL de redirecionamento requerido para a súa conta
proceed: Proceda para seguir
prompt: 'Vostede vai seguir:'
+ remote_unfollow:
+ error: Fallo
+ title: Título
+ unfollowed: Deixou de seguir
sessions:
activity: Última actividade
browser: Navegador
diff --git a/config/locales/it.yml b/config/locales/it.yml
index 7e5bfd20e..78bf8ba2b 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -3,43 +3,283 @@ it:
about:
about_mastodon_html: Mastodon è un social network gratuito e open-source. Un'alternativa decentralizzata alle piattaforme commerciali che evita che una singola compagnia monopolizzi il tuo modo di comunicare. Scegli un server di cui ti fidi — qualunque sia la tua scelta, potrai interagire con chiunque altro. Chiunque può sviluppare un suo server Mastodon e partecipare alla vita del social network.
about_this: A proposito di questo server
- closed_registrations: Al momento le iscrizioni a questo server sono chiuse.
+ administered_by: 'Amministrato da:'
+ closed_registrations: Al momento le iscrizioni a questo server sono chiuse. Tuttavia! Puoi provare a cercare un istanza diversa su cui creare un account ed avere accesso alla stessa identica rete di questa.
contact: Contatti
+ contact_missing: Non impostato
+ contact_unavailable: N/D
description_headline: Cos'è %{domain}?
domain_count_after: altri server
domain_count_before: Connesso a
- other_instances: Altri server
+ features:
+ humane_approach_title: Un approccio più umano
+ not_a_product_body: Mastodon non è una rete commerciale. Niente pubblicità, niente data mining, nessun giardino murato. Non c'è nessuna autorità centrale.
+ not_a_product_title: Tu sei una persona, non un prodotto
+ real_conversation_title: Creato per conversazioni reali
+ generic_description: "%{domain} è un server nella rete"
+ learn_more: Scopri altro
+ other_instances: Elenco istanze
source_code: Codice sorgente
- status_count_after: status
+ status_count_after: stati
status_count_before: Che hanno pubblicato
user_count_after: utenti
- user_count_before: Casa di
+ user_count_before: Home di
+ what_is_mastodon: Che cos'è Mastodon?
accounts:
follow: Segui
followers: Seguaci
following: Seguiti
+ media: Media
nothing_here: Qui non c'è nulla!
people_followed_by: Persone seguite da %{name}
people_who_follow: Persone che seguono %{name}
posts: Posts
+ posts_with_replies: Toot e repliche
remote_follow: Segui da remoto
+ reserved_username: Il nome utente è riservato
+ roles:
+ admin: Amministratore
+ moderator: Mod
unfollow: Non seguire più
+ admin:
+ account_moderation_notes:
+ account: Moderatore
+ create: Crea
+ created_at: Data
+ created_msg: Nota di moderazione creata con successo!
+ delete: Elimina
+ destroyed_msg: Nota di moderazione distrutta con successo!
+ accounts:
+ are_you_sure: Sei sicuro?
+ avatar: Avatar
+ by_domain: Dominio
+ change_email:
+ changed_msg: Account email cambiato con successo!
+ current_email: Email corrente
+ label: Cambia email
+ new_email: Nuova email
+ submit: Cambia email
+ title: Cambia email per %{username}
+ confirm: Conferma
+ confirmed: Confermato
+ demote: Declassa
+ disable: Disabilita
+ disable_two_factor_authentication: Disabilita 2FA
+ disabled: Disabilitato
+ display_name: Nome visualizzato
+ domain: Dominio
+ edit: Modifica
+ email: Email
+ enable: Abilita
+ enabled: Abilitato
+ feed_url: URL Feed
+ followers: Follower
+ followers_url: URL follower
+ follows: Follows
+ inbox_url: URL inbox
+ ip: IP
+ location:
+ all: Tutto
+ local: Locale
+ remote: Remoto
+ title: Luogo
+ login_status: Stato login
+ media_attachments: Media allegati
+ memorialize: Trasforma in memoriam
+ moderation:
+ all: Tutto
+ silenced: Silenziati
+ suspended: Sospesi
+ title: Moderazione
+ moderation_notes: Note di moderazione
+ most_recent_activity: Attività più recenti
+ most_recent_ip: IP più recenti
+ not_subscribed: Non sottoscritto
+ order:
+ alphabetic: Alfabetico
+ most_recent: Più recente
+ title: Ordine
+ outbox_url: URL outbox
+ perform_full_suspension: Esegui sospensione completa
+ profile_url: URL profilo
+ promote: Promuovi
+ protocol: Protocollo
+ public: Pubblico
+ redownload: Aggiorna avatar
+ remove_avatar: Rimuovi avatar
+ reset: Reimposta
+ reset_password: Reimposta password
+ role: Permessi
+ roles:
+ admin: Amministratore
+ moderator: Moderatore
+ staff: Staff
+ user: Utente
+ search: Cerca
+ silence: Silenzia
+ statuses: Stati
+ subscribe: Sottoscrivi
+ title: Account
+ unconfirmed_email: Email non confermata
+ undo_silenced: Rimuovi silenzia
+ undo_suspension: Rimuovi sospensione
+ username: Nome utente
+ web: Web
+ action_logs:
+ actions:
+ confirm_user: "%{name} ha confermato l'indirizzo email per l'utente %{target}"
+ create_custom_emoji: "%{name} ha caricato un nuovo emoji %{target}"
+ create_domain_block: "%{name} ha bloccato il dominio %{target}"
+ custom_emojis:
+ by_domain: Dominio
+ copied_msg: Creata con successo una copia locale dell'emoji
+ copy: Copia
+ copy_failed_msg: Impossibile creare una copia locale di questo emoji
+ created_msg: Emoji creato con successo!
+ delete: Elimina
+ destroyed_msg: Emoji distrutto con successo!
+ disable: Disabilita
+ disabled_msg: Questa emoji è stata disabilitata con successo
+ emoji: Emoji
+ enable: Abilita
+ enabled_msg: Questa emoji è stata abilitata con successo
+ image_hint: PNG fino a 50KB
+ listed: Elencato
+ new:
+ title: Aggiungi nuovo emoji personalizzato
+ overwrite: Sovrascrivi
+ shortcode: Shortcode
+ title: Emoji personalizzate
+ unlisted: Non elencato
+ update_failed_msg: Impossibile aggiornare questa emojii
+ updated_msg: Emoji aggiornata con successo!
+ upload: Carica
+ domain_blocks:
+ add_new: Aggiungi nuovo
+ created_msg: Il blocco del dominio sta venendo processato
+ destroyed_msg: Il blocco del dominio è stato rimosso
+ domain: Dominio
+ new:
+ create: Crea blocco
+ severity:
+ noop: Nessuno
+ silence: Silenzia
+ suspend: Sospendi
+ title: Nuovo blocco dominio
+ severities:
+ noop: Nessuno
+ silence: Silenzia
+ suspend: Sospendi
+ severity: Severità
+ title: Blocchi dominio
+ email_domain_blocks:
+ add_new: Aggiungi nuovo
+ delete: Elimina
+ domain: Dominio
+ new:
+ create: Aggiungi dominio
+ instances:
+ domain_name: Dominio
+ reset: Reimposta
+ search: Cerca
+ title: Istanze conosciute
+ invites:
+ filter:
+ all: Tutto
+ available: Disponibile
+ expired: Scaduto
+ title: Filtro
+ title: Inviti
+ reports:
+ account:
+ note: note
+ are_you_sure: Sei sicuro?
+ assign_to_self: Assegna a me
+ comment:
+ none: Nessuno
+ delete: Elimina
+ id: ID
+ mark_as_resolved: Segna come risolto
+ mark_as_unresolved: Segna come non risolto
+ notes:
+ create: Aggiungi nota
+ create_and_resolve: Risolvi con nota
+ create_and_unresolve: Riapri con nota
+ delete: Elimina
+ report_contents: Contenuti
+ resolved: Risolto
+ status: Stati
+ target: Obbiettivo
+ unassign: Non assegnare
+ unresolved: Non risolto
+ updated_at: Aggiornato
+ view: Mostra
+ settings:
+ activity_api_enabled:
+ title: Pubblica statistiche aggregate circa l'attività dell'utente
+ peers_api_enabled:
+ title: Pubblica elenco di istanze scoperte
+ registrations:
+ min_invite_role:
+ disabled: Nessuno
+ show_staff_badge:
+ title: Mostra badge staff
+ site_description:
+ title: Descrizione istanza
+ site_terms:
+ title: Termini di servizio personalizzati
+ site_title: Nome istanza
+ timeline_preview:
+ title: Anteprima timeline
+ title: Impostazioni sito
+ statuses:
+ batch:
+ delete: Elimina
+ nsfw_off: NSFW OFF
+ nsfw_on: NSFW ON
+ execute: Esegui
+ failed_to_execute: Impossibile eseguire
+ media:
+ hide: Nascondi media
+ show: Mostra media
+ title: Media
+ no_media: Nessun media
+ with_media: con media
+ subscriptions:
+ callback_url: URL Callback
+ confirmed: Confermato
+ expires_in: Scade in
+ topic: Argomento
+ title: Amministrazione
application_mailer:
+ notification_preferences: Cambia preferenze email
+ salutation: "%{name},"
settings: 'Cambia le impostazioni per le e-mail: %{link}'
view: 'Guarda:'
+ view_profile: Mostra profilo
+ view_status: Mostra stati
applications:
+ created: Applicazione creata con successo
+ destroyed: Applicazione eliminata con successo
invalid_url: L'URL fornito non è valido
auth:
+ change_password: Password
+ confirm_email: Conferma email
+ delete_account: Elimina account
didnt_get_confirmation: Non hai ricevuto le istruzioni di conferma?
forgot_password: Hai dimenticato la tua password?
login: Entra
logout: Logout
+ migrate_account: Sposta ad un account differente
+ or: o
register: Iscriviti
+ register_elsewhere: Iscriviti su un altro server
resend_confirmation: Invia di nuovo le istruzioni di conferma
reset_password: Resetta la password
security: Credenziali
set_new_password: Imposta una nuova password
authorize_follow:
+ already_following: Stai già seguendo questo account
error: Sfortunatamente c'è stato un errore nel consultare l'account remoto
follow: Segui
title: Segui %{acct}
@@ -161,6 +401,9 @@ it:
manual_instructions: 'Se non puoi scannerizzare il QR code e hai bisogno di inserirlo manualmente, questo è il codice segreto in chiaro:'
setup: Configura
wrong_code: Il codice inserito non è corretto! Assicurati che l'orario del server e l'orario del telefono siano corretti.
+ user_mailer:
+ welcome:
+ title: Benvenuto a bordo, %{name}!
users:
invalid_email: L'indirizzo e-mail inserito non è valido
invalid_otp_token: Codice d'accesso non valido
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index b23c02754..aaebec654 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -68,7 +68,7 @@ ja:
current_email: 現在のメールアドレス
label: メールアドレスを変更
new_email: 新しいメールアドレス
- submit: Change Email
+ submit: メールアドレスの変更
title: "%{username} さんのメールアドレスを変更"
confirm: 確認
confirmed: 確認済み
@@ -259,6 +259,9 @@ ja:
created_msg: レポートメモを書き込みました!
destroyed_msg: レポートメモを削除しました!
reports:
+ account:
+ note: メモ
+ report: レポート
action_taken_by: レポート処理者
are_you_sure: 本当に実行しますか?
assign_to_self: 担当になる
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 3470085cf..0f3c6483f 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -4,6 +4,7 @@ ko:
about_hashtag_html: "#%{hashtag} 라는 해시태그가 붙은 공개 툿 입니다. 같은 연합에 속한 임의의 인스턴스에 계정을 생성하면 당신도 대화에 참여할 수 있습니다."
about_mastodon_html: Mastodon은 오픈 소스 기반의 소셜 네트워크 서비스 입니다. 상용 플랫폼의 대체로서 분산형 구조를 채택해, 여러분의 대화가 한 회사에 독점되는 것을 방지합니다. 신뢰할 수 있는 인스턴스를 선택하세요 — 어떤 인스턴스를 고르더라도, 누구와도 대화할 수 있습니다. 누구나 자신만의 Mastodon 인스턴스를 만들 수 있으며, 아주 매끄럽게 소셜 네트워크에 참가할 수 있습니다.
about_this: 이 인스턴스에 대해서
+ administered_by: '관리자:'
closed_registrations: 현재 이 인스턴스에서는 신규 등록을 받고 있지 않습니다.
contact: 연락처
contact_missing: 미설정
@@ -60,7 +61,15 @@ ko:
destroyed_msg: 모더레이션 기록이 성공적으로 삭제되었습니다!
accounts:
are_you_sure: 정말로 실행하시겠습니까?
+ avatar: 아바타
by_domain: 도메인
+ change_email:
+ changed_msg: 이메일이 성공적으로 바뀌었습니다!
+ current_email: 현재 이메일 주소
+ label: 이메일 주소 변경
+ new_email: 새 이메일 주소
+ submit: 이메일 주소 변경
+ title: "%{username}의 이메일 주소 변경"
confirm: 확인
confirmed: 확인됨
demote: 모더레이터 강등
@@ -108,6 +117,7 @@ ko:
public: 전체 공개
push_subscription_expires: PuSH 구독 기간 만료
redownload: 아바타 업데이트
+ remove_avatar: 아바타 지우기
reset: 초기화
reset_password: 비밀번호 초기화
resubscribe: 다시 구독
@@ -128,6 +138,7 @@ ko:
statuses: 툿 수
subscribe: 구독하기
title: 계정
+ unconfirmed_email: 미확인 된 이메일 주소
undo_silenced: 침묵 해제
undo_suspension: 정지 해제
unsubscribe: 구독 해제
@@ -135,6 +146,8 @@ ko:
web: 웹
action_logs:
actions:
+ assigned_to_self_report: "%{name}이 리포트 %{target}을 자신에게 할당했습니다"
+ change_email_user: "%{name}이 %{target}의 이메일 주소를 변경했습니다"
confirm_user: "%{name}이 %{target}의 이메일 주소를 컨펌했습니다"
create_custom_emoji: "%{name}이 새로운 에모지 %{target}를 추가했습니다"
create_domain_block: "%{name}이 도메인 %{target}를 차단했습니다"
@@ -150,10 +163,13 @@ ko:
enable_user: "%{name}이 %{target}의 로그인을 활성화 했습니다"
memorialize_account: "%{name}이 %{target}의 계정을 메모리엄으로 전환했습니다"
promote_user: "%{name}이 %{target}를 승급시켰습니다"
+ remove_avatar_user: "%{name}이 %{target}의 아바타를 지웠습니다"
+ reopen_report: "%{name}이 리포트 %{target}을 다시 열었습니다"
reset_password_user: "%{name}이 %{target}의 암호를 초기화했습니다"
resolve_report: "%{name}이 %{target} 신고를 처리됨으로 변경하였습니다"
silence_account: "%{name}이 %{target}의 계정을 뮤트시켰습니다"
suspend_account: "%{name}이 %{target}의 계정을 정지시켰습니다"
+ unassigned_report: "%{name}이 리포트 %{target}을 할당 해제했습니다"
unsilence_account: "%{name}이 %{target}에 대한 뮤트를 해제했습니다"
unsuspend_account: "%{name}이 %{target}에 대한 정지를 해제했습니다"
update_custom_emoji: "%{name}이 에모지 %{target}를 업데이트 했습니다"
@@ -241,28 +257,48 @@ ko:
expired: 만료됨
title: 필터
title: 초대
+ report_notes:
+ created_msg: 리포트 노트가 성공적으로 작성되었습니다!
+ destroyed_msg: 리포트 노트가 성공적으로 삭제되었습니다!
reports:
+ account:
+ note: 노트
+ report: 리포트
action_taken_by: 신고 처리자
are_you_sure: 정말로 실행하시겠습니까?
+ assign_to_self: 나에게 할당 됨
+ assigned: 할당 된 모더레이터
comment:
none: 없음
+ created_at: 리포트 시각
delete: 삭제
id: ID
mark_as_resolved: 해결 완료 처리
+ mark_as_unresolved: 미해결로 표시
+ notes:
+ create: 노트 추가
+ create_and_resolve: 노트를 작성하고 해결됨으로 표시
+ create_and_unresolve: 노트 작성과 함께 미해결로 표시
+ delete: 삭제
+ placeholder: 이 리포트에 대한 조치, 다른 업데이트 사항에 대해 설명합니다…
nsfw:
'false': NSFW 꺼짐
'true': NSFW 켜짐
+ reopen: 리포트 다시 열기
report: '신고 #%{id}'
report_contents: 내용
reported_account: 신고 대상 계정
reported_by: 신고자
resolved: 해결됨
+ resolved_msg: 리포트가 성공적으로 해결되었습니다!
silence_account: 계정을 침묵 처리
status: 상태
suspend_account: 계정을 정지
target: 대상
title: 신고
+ unassign: 할당 해제
unresolved: 미해결
+ updated_at: 업데이트 시각
view: 표시
settings:
activity_api_enabled:
@@ -383,6 +419,7 @@ ko:
security: 보안
set_new_password: 새 비밀번호
authorize_follow:
+ already_following: 이미 이 계정을 팔로우 하고 있습니다
error: 리모트 계정을 확인하는 도중 오류가 발생했습니다
follow: 팔로우
follow_request: '당신은 다음 계정에 팔로우 신청을 했습니다:'
@@ -475,6 +512,7 @@ ko:
'21600': 6 시간
'3600': 1 시간
'43200': 12 시간
+ '604800': 1주일
'86400': 하루
expires_in_prompt: 영원히
generate: 생성
@@ -547,7 +585,7 @@ ko:
quadrillion: Q
thousand: K
trillion: T
- unit: ''
+ unit: "."
pagination:
newer: 새로운 툿
next: 다음
@@ -578,6 +616,10 @@ ko:
missing_resource: 리디렉션 대상을 찾을 수 없습니다
proceed: 팔로우 하기
prompt: '팔로우 하려 하고 있습니다:'
+ remote_unfollow:
+ error: 에러
+ title: 타이틀
+ unfollowed: 언팔로우됨
sessions:
activity: 마지막 활동
browser: 브라우저
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index 2342ef6a2..64bc71874 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -4,6 +4,7 @@ nl:
about_hashtag_html: Dit zijn openbare toots die getagged zijn met #%{hashtag}. Je kunt er op reageren of iets anders mee doen als je op Mastodon (of ergens anders in de fediverse) een account hebt.
about_mastodon_html: Mastodon is een sociaal netwerk dat gebruikt maakt van open webprotocollen en vrije software. Het is net zoals e-mail gedecentraliseerd.
about_this: Over deze server
+ administered_by: 'Beheerd door:'
closed_registrations: Registreren op deze server is momenteel uitgeschakeld.
contact: Contact
contact_missing: Niet ingesteld
@@ -60,7 +61,15 @@ nl:
destroyed_msg: Verwijderen van opmerking voor moderatoren geslaagd!
accounts:
are_you_sure: Weet je het zeker?
+ avatar: Avatar
by_domain: Domein
+ change_email:
+ changed_msg: E-mailadres van account succesvol veranderd!
+ current_email: Huidig e-mailadres
+ label: E-mailadres veranderen
+ new_email: Nieuw e-mailadres
+ submit: E-mailadres veranderen
+ title: E-mailadres veranderen voor %{username}
confirm: Bevestigen
confirmed: Bevestigd
demote: Degraderen
@@ -108,6 +117,7 @@ nl:
public: Openbaar
push_subscription_expires: PuSH-abonnement verloopt op
redownload: Avatar vernieuwen
+ remove_avatar: Avatar verwijderen
reset: Opnieuw
reset_password: Wachtwoord opnieuw instellen
resubscribe: Opnieuw abonneren
@@ -128,6 +138,7 @@ nl:
statuses: Toots
subscribe: Abonneren
title: Accounts
+ unconfirmed_email: Onbevestigd e-mailadres
undo_silenced: Niet meer negeren
undo_suspension: Niet meer opschorten
unsubscribe: Opzeggen
@@ -135,6 +146,8 @@ nl:
web: Webapp
action_logs:
actions:
+ assigned_to_self_report: "%{name} heeft gerapporteerde toot %{target} aan zichzelf toegewezen"
+ change_email_user: "%{name} veranderde het e-mailadres van gebruiker %{target}"
confirm_user: E-mailadres van gebruiker %{target} is door %{name} bevestigd
create_custom_emoji: Nieuwe emoji %{target} is door %{name} geüpload
create_domain_block: Domein %{target} is door %{name} geblokkeerd
@@ -150,10 +163,13 @@ nl:
enable_user: Inloggen voor %{target} is door %{name} ingeschakeld
memorialize_account: Account %{target} is door %{name} in een in-memoriampagina veranderd
promote_user: Gebruiker %{target} is door %{name} gepromoveerd
+ remove_avatar_user: "%{name} verwijderde de avatar van %{target}"
+ reopen_report: "%{name} heeft gerapporteerde toot %{target} heropend"
reset_password_user: Wachtwoord van gebruiker %{target} is door %{name} opnieuw ingesteld
- resolve_report: Gerapporteerde toots van %{target} zijn door %{name} verworpen
+ resolve_report: "%{name} heeft gerapporteerde toot %{target} opgelost"
silence_account: Account %{target} is door %{name} genegeerd
suspend_account: Account %{target} is door %{name} opgeschort
+ unassigned_report: "%{name} heeft het toewijzen van gerapporteerde toot %{target} ongedaan gemaakt"
unsilence_account: Negeren van account %{target} is door %{name} opgeheven
unsuspend_account: Opschorten van account %{target} is door %{name} opgeheven
update_custom_emoji: Emoji %{target} is door %{name} bijgewerkt
@@ -239,28 +255,48 @@ nl:
expired: Verlopen
title: Filter
title: Uitnodigingen
+ report_notes:
+ created_msg: Opmerking bij gerapporteerde toot succesvol aangemaakt!
+ destroyed_msg: Opmerking bij gerapporteerde toot succesvol verwijderd!
reports:
+ account:
+ note: opmerking
+ report: gerapporteerde toot
action_taken_by: Actie uitgevoerd door
are_you_sure: Weet je het zeker?
+ assign_to_self: Aan mij toewijzen
+ assigned: Toegewezen moderator
comment:
none: Geen
+ created_at: Gerapporteerd op
delete: Verwijderen
id: ID
mark_as_resolved: Markeer als opgelost
+ mark_as_unresolved: Markeer als onopgelost
+ notes:
+ create: Opmerking toevoegen
+ create_and_resolve: Oplossen met opmerking
+ create_and_unresolve: Heropenen met opmerking
+ delete: Verwijderen
+ placeholder: Beschrijf welke acties zijn ondernomen of andere opmerkingen over deze gerapporteerde toot…
nsfw:
'false': Media tonen
'true': Media verbergen
+ reopen: Gerapporteerde toot heropenen
report: 'Gerapporteerde toot #%{id}'
report_contents: Inhoud
reported_account: Gerapporteerde account
reported_by: Gerapporteerd door
resolved: Opgelost
+ resolved_msg: Gerapporteerde toot succesvol opgelost!
silence_account: Account negeren
status: Toot
suspend_account: Account opschorten
target: Gerapporteerde account
title: Gerapporteerde toots
+ unassign: Niet meer toewijzen
unresolved: Onopgelost
+ updated_at: Bijgewerkt
view: Weergeven
settings:
activity_api_enabled:
@@ -381,6 +417,7 @@ nl:
security: Beveiliging
set_new_password: Nieuw wachtwoord instellen
authorize_follow:
+ already_following: Je volgt dit account al
error: Helaas, er is een fout opgetreden bij het opzoeken van de externe account
follow: Volgen
follow_request: 'Jij hebt een volgverzoek ingediend bij:'
@@ -473,6 +510,7 @@ nl:
'21600': 6 uur
'3600': 1 uur
'43200': 12 uur
+ '604800': 1 week
'86400': 1 dag
expires_in_prompt: Nooit
generate: Genereren
@@ -576,6 +614,10 @@ nl:
missing_resource: Kon vereiste doorverwijzings-URL voor jouw account niet vinden
proceed: Ga door om te volgen
prompt: 'Jij gaat volgen:'
+ remote_unfollow:
+ error: Fout
+ title: Titel
+ unfollowed: Ontvolgd
sessions:
activity: Laatst actief
browser: Webbrowser
@@ -664,6 +706,83 @@ nl:
reblogged: boostte
sensitive_content: Gevoelige inhoud
terms:
+ body_html: |
+
Privacy Policy
+
What information do we collect?
+
+
+
Basic account information: If you register on this server, you may be asked to enter a username, an e-mail address and a password. You may also enter additional profile information such as a display name and biography, and upload a profile picture and header image. The username, display name, biography, profile picture and header image are always listed publicly.
+
Posts, following and other public information: The list of people you follow is listed publicly, the same is true for your followers. When you submit a message, the date and time is stored as well as the application you submitted the message from. Messages may contain media attachments, such as pictures and videos. Public and unlisted posts are available publicly. When you feature a post on your profile, that is also publicly available information. Your posts are delivered to your followers, in some cases it means they are delivered to different servers and copies are stored there. When you delete posts, this is likewise delivered to your followers. The action of reblogging or favouriting another post is always public.
+
Direct and followers-only posts: All posts are stored and processed on the server. Followers-only posts are delivered to your followers and users who are mentioned in them, and direct posts are delivered only to users mentioned in them. In some cases it means they are delivered to different servers and copies are stored there. We make a good faith effort to limit the access to those posts only to authorized persons, but other servers may fail to do so. Therefore it's important to review servers your followers belong to. You may toggle an option to approve and reject new followers manually in the settings. Please keep in mind that the operators of the server and any receiving server may view such messages, and that recipients may screenshot, copy or otherwise re-share them. Do not share any dangerous information over Mastodon.
+
IPs and other metadata: When you log in, we record the IP address you log in from, as well as the name of your browser application. All the logged in sessions are available for your review and revocation in the settings. The latest IP address used is stored for up to 12 months. We also may retain server logs which include the IP address of every request to our server.
+
+
+
+
+
What do we use your information for?
+
+
Any of the information we collect from you may be used in the following ways:
+
+
+
To provide the core functionality of Mastodon. You can only interact with other people's content and post your own content when you are logged in. For example, you may follow other people to view their combined posts in your own personalized home timeline.
+
To aid moderation of the community, for example comparing your IP address with other known ones to determine ban evasion or other violations.
+
The email address you provide may be used to send you information, notifications about other people interacting with your content or sending you messages, and to respond to inquiries, and/or other requests or questions.
+
+
+
+
+
How do we protect your information?
+
+
We implement a variety of security measures to maintain the safety of your personal information when you enter, submit, or access your personal information. Among other things, your browser session, as well as the traffic between your applications and the API, are secured with SSL, and your password is hashed using a strong one-way algorithm. You may enable two-factor authentication to further secure access to your account.
+
+
+
+
What is our data retention policy?
+
+
We will make a good faith effort to:
+
+
+
Retain server logs containing the IP address of all requests to this server, in so far as such logs are kept, no more than 90 days.
+
Retain the IP addresses associated with registered users no more than 12 months.
+
+
+
You can request and download an archive of your content, including your posts, media attachments, profile picture, and header image.
+
+
You may irreversibly delete your account at any time.
+
+
+
+
Do we use cookies?
+
+
Yes. Cookies are small files that a site or its service provider transfers to your computer's hard drive through your Web browser (if you allow). These cookies enable the site to recognize your browser and, if you have a registered account, associate it with your registered account.
+
+
We use cookies to understand and save your preferences for future visits.
+
+
+
+
Do we disclose any information to outside parties?
+
+
We do not sell, trade, or otherwise transfer to outside parties your personally identifiable information. This does not include trusted third parties who assist us in operating our site, conducting our business, or servicing you, so long as those parties agree to keep this information confidential. We may also release your information when we believe release is appropriate to comply with the law, enforce our site policies, or protect ours or others rights, property, or safety.
+
+
Your public content may be downloaded by other servers in the network. Your public and followers-only posts are delivered to the servers where your followers reside, and direct messages are delivered to the servers of the recipients, in so far as those followers or recipients reside on a different server than this.
+
+
When you authorize an application to use your account, depending on the scope of permissions you approve, it may access your public profile information, your following list, your followers, your lists, all your posts, and your favourites. Applications can never access your e-mail address or password.
Our site, products and services are all directed to people who are at least 13 years old. If this server is in the USA, and you are under the age of 13, per the requirements of COPPA (Children's Online Privacy Protection Act) do not use this site.
+
+
+
+
Changes to our Privacy Policy
+
+
If we decide to change our privacy policy, we will post those changes on this page.
+
+
This document is CC-BY-SA. It was last updated March 7, 2018.
title: "%{instance} Terms of Service and Privacy Policy"
themes:
default: Mastodon
diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml
index d3c1d532b..aeafe77bd 100644
--- a/config/locales/pt-BR.yml
+++ b/config/locales/pt-BR.yml
@@ -4,6 +4,7 @@ pt-BR:
about_hashtag_html: Estes são toots públicos com a hashtag #%{hashtag}. Você pode interagir com eles se tiver uma conta em qualquer lugar no fediverso.
about_mastodon_html: Mastodon é uma rede social baseada em protocolos abertos e software gratuito e de código aberto. É descentralizada como e-mail.
about_this: Sobre
+ administered_by: 'Administrado por:'
closed_registrations: Os cadastros estão atualmente fechados nesta instância. No entanto, você pode procurar uma instância diferente na qual possa criar uma conta e acessar a mesma rede por lá.
contact: Contato
contact_missing: Não definido
@@ -60,7 +61,15 @@ pt-BR:
destroyed_msg: Nota de moderação excluída com sucesso!
accounts:
are_you_sure: Você tem certeza?
+ avatar: Avatar
by_domain: Domínio
+ change_email:
+ changed_msg: E-mail da conta modificado com sucesso!
+ current_email: E-mail atual
+ label: Mudar e-mail
+ new_email: Novo e-mail
+ submit: Mudar e-mail
+ title: Mudar e-mail para %{username}
confirm: Confirmar
confirmed: Confirmado
demote: Rebaixar
@@ -108,6 +117,7 @@ pt-BR:
public: Público
push_subscription_expires: Inscrição PuSH expira
redownload: Atualizar avatar
+ remove_avatar: Remover avatar
reset: Anular
reset_password: Modificar senha
resubscribe: Reinscrever-se
@@ -128,6 +138,7 @@ pt-BR:
statuses: Postagens
subscribe: Inscrever-se
title: Contas
+ unconfirmed_email: E-mail não confirmado
undo_silenced: Retirar silenciamento
undo_suspension: Retirar suspensão
unsubscribe: Desinscrever-se
@@ -135,6 +146,8 @@ pt-BR:
web: Web
action_logs:
actions:
+ assigned_to_self_report: "%{name} designou a denúncia %{target} para si"
+ change_email_user: "%{name} mudou o endereço de e-mail do usuário %{target}"
confirm_user: "%{name} confirmou o endereço de e-mail do usuário %{target}"
create_custom_emoji: "%{name} enviou o emoji novo %{target}"
create_domain_block: "%{name} bloqueou o domínio %{target}"
@@ -150,10 +163,13 @@ pt-BR:
enable_user: "%{name} habilitou o acesso para o usuário %{target}"
memorialize_account: "%{name} transformou a conta de %{target} em um memorial"
promote_user: "%{name} promoveu o usuário %{target}"
+ remove_avatar_user: "%{name} removeu o avatar de %{target}"
+ reopen_report: "%{name} reabriu a denúncia %{target}"
reset_password_user: "%{name} redefiniu a senha do usuário %{target}"
- resolve_report: "%{name} dispensou a denúncia %{target}"
+ resolve_report: "%{name} resolveu a denúncia %{target}"
silence_account: "%{name} silenciou a conta de %{target}"
suspend_account: "%{name} suspendeu a conta de %{target}"
+ unassigned_report: "%{name} desatribuiu a denúncia %{target}"
unsilence_account: "%{name} desativou o silêncio de %{target}"
unsuspend_account: "%{name} desativou a suspensão de %{target}"
update_custom_emoji: "%{name} atualizou o emoji %{target}"
@@ -239,28 +255,48 @@ pt-BR:
expired: Expirados
title: Filtro
title: Convites
+ report_notes:
+ created_msg: Nota de denúncia criada com sucesso!
+ destroyed_msg: Nota de denúncia excluída com sucesso!
reports:
+ account:
+ note: nota
+ report: denúncia
action_taken_by: Ação realizada por
are_you_sure: Você tem certeza?
+ assign_to_self: Designar para mim
+ assigned: Moderador designado
comment:
none: Nenhum
+ created_at: Denunciado
delete: Excluir
id: ID
mark_as_resolved: Marcar como resolvido
+ mark_as_unresolved: Marcar como não resolvido
+ notes:
+ create: Adicionar nota
+ create_and_resolve: Resolver com nota
+ create_and_unresolve: Reabrir com nota
+ delete: Excluir
+ placeholder: Descreva que ações foram tomadas, ou quaisquer atualizações sobre esta denúncia…
nsfw:
'false': Mostrar mídias anexadas
'true': Esconder mídias anexadas
+ reopen: Reabrir denúncia
report: 'Denúncia #%{id}'
report_contents: Conteúdos
reported_account: Conta denunciada
reported_by: Denunciada por
resolved: Resolvido
+ resolved_msg: Denúncia resolvida com sucesso!
silence_account: Silenciar conta
status: Status
suspend_account: Suspender conta
target: Alvo
title: Denúncias
+ unassign: Desatribuir
unresolved: Não resolvido
+ updated_at: Atualizado
view: Visualizar
settings:
activity_api_enabled:
@@ -381,6 +417,7 @@ pt-BR:
security: Segurança
set_new_password: Definir uma nova senha
authorize_follow:
+ already_following: Você já está seguindo esta conta
error: Infelizmente, ocorreu um erro ao buscar a conta remota
follow: Seguir
follow_request: 'Você mandou uma solicitação de seguidor para:'
@@ -473,6 +510,7 @@ pt-BR:
'21600': 6 horas
'3600': 1 hora
'43200': 12 horas
+ '604800': 1 semana
'86400': 1 dia
expires_in_prompt: Nunca
generate: Gerar
@@ -576,6 +614,9 @@ pt-BR:
missing_resource: Não foi possível encontrar a URL de direcionamento para a sua conta
proceed: Prosseguir para seguir
prompt: 'Você irá seguir:'
+ remote_unfollow:
+ error: Erro
+ title: Título
sessions:
activity: Última atividade
browser: Navegador
diff --git a/config/locales/simple_form.ar.yml b/config/locales/simple_form.ar.yml
index 414f0c342..28cfa8ab7 100644
--- a/config/locales/simple_form.ar.yml
+++ b/config/locales/simple_form.ar.yml
@@ -5,8 +5,15 @@ ar:
defaults:
avatar: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير 2MB. سيتم تصغيره إلى 400x400px
digest: تُرسَل إليك بعد مُضيّ مدة مِن خمول نشاطك و فقط إذا ما تلقيت رسائل شخصية مباشِرة أثناء فترة غيابك مِن الشبكة
+ display_name:
+ one: 1 حرف باقي
+ other: %{count} حروف متبقية
+ fields: يُمكنك عرض 4 عناصر على شكل جدول في ملفك الشخصي
header: ملف PNG أو GIF أو JPG. حجمه على أقصى تصدير 2MB. سيتم تصغيره إلى 700x335px
locked: يتطلب منك الموافقة يدويا على طلبات المتابعة
+ note:
+ one: 1 حرف متبقي
+ other: %{count} حروف متبقية
setting_noindex: ذلك يؤثر على حالة ملفك الشخصي و صفحاتك
setting_theme: ذلك يؤثر على الشكل الذي سيبدو عليه ماستدون عندما تقوم بالدخول مِن أي جهاز.
imports:
@@ -16,6 +23,10 @@ ar:
user:
filtered_languages: سوف يتم تصفية و إخفاء اللغات المختارة من خيوطك العمومية
labels:
+ account:
+ fields:
+ name: التسمية
+ value: المحتوى
defaults:
avatar: الصورة الرمزية
confirm_new_password: تأكيد كلمة السر الجديدة
@@ -25,6 +36,7 @@ ar:
display_name: الإسم المعروض
email: عنوان البريد الإلكتروني
expires_in: تنتهي مدة صلاحيته بعد
+ fields: واصفات بيانات الملف الشخصي
filtered_languages: اللغات التي تم تصفيتها
header: الرأسية
locale: اللغة
diff --git a/config/locales/simple_form.ca.yml b/config/locales/simple_form.ca.yml
index 300da45a5..1b04da90a 100644
--- a/config/locales/simple_form.ca.yml
+++ b/config/locales/simple_form.ca.yml
@@ -8,6 +8,7 @@ ca:
display_name:
one: 1 càracter restant
other: %{count} càracters restans
+ fields: Pots tenir fins a 4 elements que es mostren com a taula al teu perfil
header: PNG, GIF o JPG. Màxim 2MB. S'escalarà a 700x335px
locked: Requereix que aprovis manualment els seguidors
note:
@@ -22,6 +23,10 @@ ca:
user:
filtered_languages: Les llengües seleccionades s'eliminaran de les línies de temps públiques
labels:
+ account:
+ fields:
+ name: Etiqueta
+ value: Contingut
defaults:
avatar: Avatar
confirm_new_password: Confirma la contrasenya nova
@@ -31,6 +36,7 @@ ca:
display_name: Nom visible
email: Adreça de correu electrònic
expires_in: Expira després
+ fields: Metadades del perfil
filtered_languages: Llengües filtrades
header: Capçalera
locale: Llengua
diff --git a/config/locales/simple_form.eu.yml b/config/locales/simple_form.eu.yml
new file mode 100644
index 000000000..9664357ab
--- /dev/null
+++ b/config/locales/simple_form.eu.yml
@@ -0,0 +1,6 @@
+---
+eu:
+ simple_form:
+ hints:
+ defaults:
+ avatar: PNG, GIF edo JPG. Gehienez 2MB. 400x400px neurrira eskalatuko da
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index 71674199d..88e1b8873 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -8,6 +8,7 @@ fr:
display_name:
one: 1 caractère restant
other: %{count} caractères restants
+ fields: Vous pouvez avoir jusqu'à 4 éléments affichés en tant que tableau sur votre profil
header: Au format PNG, GIF ou JPG. 2 Mo maximum. Sera réduit à 700x335px
locked: Vous devrez approuver chaque abonné⋅e et vos statuts ne s’afficheront qu’à vos abonné⋅es
note:
@@ -22,6 +23,10 @@ fr:
user:
filtered_languages: Les langues sélectionnées seront filtrées hors de vos fils publics pour vous
labels:
+ account:
+ fields:
+ name: Étiquette
+ value: Contenu
defaults:
avatar: Image de profil
confirm_new_password: Confirmation du nouveau mot de passe
@@ -31,6 +36,7 @@ fr:
display_name: Nom public
email: Adresse courriel
expires_in: Expire après
+ fields: Métadonnées du profil
filtered_languages: Langues filtrées
header: Image d’en-tête
locale: Langue
diff --git a/config/locales/simple_form.gl.yml b/config/locales/simple_form.gl.yml
index 4dcdd0459..a4903885e 100644
--- a/config/locales/simple_form.gl.yml
+++ b/config/locales/simple_form.gl.yml
@@ -8,6 +8,7 @@ gl:
display_name:
one: 1 caracter restante
other: %{count} caracteres restantes
+ fields: Pode ter ate 4 elementos no seu perfil mostrados como unha táboa
header: PNG, GIF ou JPG. Como moito 2MB. Será reducida a 700x335px
locked: Require que vostede aprove as seguidoras de xeito manual
note:
@@ -22,6 +23,10 @@ gl:
user:
filtered_languages: Os idiomas marcados filtraranse das liñas temporais públicas para vostede
labels:
+ account:
+ fields:
+ name: Etiqueta
+ value: Contido
defaults:
avatar: Avatar
confirm_new_password: Confirme o novo contrasinal
@@ -31,6 +36,7 @@ gl:
display_name: Nome mostrado
email: enderezo correo electrónico
expires_in: Caducidade despois de
+ fields: Metadatos do perfil
filtered_languages: Idiomas filtrados
header: Cabezallo
locale: Idioma
diff --git a/config/locales/simple_form.it.yml b/config/locales/simple_form.it.yml
index b2fcef109..5d9ae18f5 100644
--- a/config/locales/simple_form.it.yml
+++ b/config/locales/simple_form.it.yml
@@ -3,45 +3,77 @@ it:
simple_form:
hints:
defaults:
- avatar: PNG, GIF o JPG. Al massimo 2MB. Sarà ridotto a 400x400px
- display_name: Al massimo 30 characters
- header: PNG, GIF or JPG. Al massimo 2MB. Sarà ridotto a 700x335px
- locked: Richiede la tua approvazione per i nuovi seguaci e rende i nuovi post automaticamente visibili solo ai seguaci
- note: Al massimo 160 caratteri
+ avatar: PNG, GIF o JPG. Al massimo 2MB. Verranno scalate a 400x400px
+ digest: Inviata solo dopo un lungo periodo di intattività e solo se hai ricevuto qualsiasi messaggio personale in tua assenza
+ display_name:
+ one: 1 carattere rimanente
+ other: %{count} caratteri rimanenti
+ fields: Puoi avere fino a 4 voci visualizzate come una tabella sul tuo profilo
+ header: PNG, GIF o JPG. Al massimo 2MB. Verranno scalate a 700x335px
+ locked: Richiede che approvi i follower manualmente
+ note:
+ one: 1 carattere rimanente
+ other: %{count} caratteri rimanenti
+ setting_noindex: Coinvolge il tuo profilo pubblico e le pagine di stato
+ setting_theme: Coinvolge il modo in cui Mastodon verrà visualizzato quando sarai collegato da qualsiasi dispositivo.
imports:
- data: CSV esportato da un altro server Mastodon
+ data: File CSV esportato da un altra istanza di Mastodon
+ sessions:
+ otp: Inserisci il codice due-fattori dal tuo telefono o usa uno dei codici di recupero.
+ user:
+ filtered_languages: Le lingue selezionate verranno filtrate dalla timeline pubblica per te
labels:
+ account:
+ fields:
+ name: Etichetta
+ value: Contenuto
defaults:
avatar: Avatar
- confirm_new_password: Conferma la nuova password
- confirm_password: Conferma la password
+ confirm_new_password: Conferma nuova password
+ confirm_password: Conferma password
current_password: Password corrente
data: Data
- display_name: Nome pubblico
- email: Indirizzo e-mail
+ display_name: Nome visualizzato
+ email: Indirizzo email
+ expires_in: Scade dopo
+ fields: Metadata profilo
+ filtered_languages: Lingue filtrate
header: Header
locale: Lingua
- locked: Rendi l'account privato
+ locked: Blocca account
+ max_uses: Numero massimo di utilizzi
new_password: Nuova password
- note: Biografia
- otp_attempt: Codice d'accesso
+ note: Bio
+ otp_attempt: Codice due-fattori
password: Password
- setting_boost_modal: Mostra finestra di conferma prima di condividere
- setting_default_privacy: Privacy del post
- type: Importa
- username: Username
+ setting_auto_play_gif: Play automatico GIF animate
+ setting_boost_modal: Mostra dialogo di conferma prima del boost
+ setting_default_privacy: Privacy post
+ setting_default_sensitive: Segna sempre i media come sensibili
+ setting_delete_modal: Mostra dialogo di conferma prima di eliminare un toot
+ setting_display_sensitive_media: Mostra sempre i media segnati come sensibili
+ setting_noindex: Non indicizzare dai motori di ricerca
+ setting_reduce_motion: Riduci movimento nelle animazioni
+ setting_system_font_ui: Usa il carattere di default del sistema
+ setting_theme: Tema sito
+ setting_unfollow_modal: Mostra dialogo di conferma prima di smettere di seguire qualcuno
+ severity: Severità
+ type: Tipo importazione
+ username: Nome utente
+ username_or_email: Nome utente o email
interactions:
- must_be_follower: Blocca notifiche da chi non ti segue
- must_be_following: Blocca notifiche da chi non segui
+ must_be_follower: Blocca notifiche dai non follower
+ must_be_following: Blocca notifiche dalle persone che non segui
+ must_be_following_dm: Blocca i messaggi diretti dalle persone che non segui
notification_emails:
- digest: Invia riassunto via e-mail
- favourite: Invia e-mail quando qualcuno apprezza i tuoi status
- follow: Invia e-mail quando qualcuno ti segue
- follow_request: Invia e-mail quando qualcuno ti richiede di seguirti
- mention: Invia e-mail quando qualcuno ti menziona
- reblog: Invia e-mail quando qualcuno condivide i tuoi status
+ digest: Invia email riassuntive
+ favourite: Invia email quando segna come preferito al tuo stato
+ follow: Invia email quando qualcuno ti segue
+ follow_request: Invia email quando qualcuno richiede di seguirti
+ mention: Invia email quando qualcuno ti menziona
+ reblog: Invia email quando qualcuno da un boost al tuo stato
'no': 'No'
required:
mark: "*"
text: richiesto
- 'yes': Sì
+ 'yes': Si
diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml
index d7cccfc54..6b2d93454 100644
--- a/config/locales/simple_form.ja.yml
+++ b/config/locales/simple_form.ja.yml
@@ -6,6 +6,7 @@ ja:
avatar: 2MBまでのPNGやGIF、JPGが利用可能です。400x400pxまで縮小されます
digest: 長期間使用していない場合と不在時に返信を受けた場合のみ送信されます
display_name: あと%{count}文字入力できます。
+ fields: プロフィールに表として4つまでの項目を表示することができます
header: 2MBまでのPNGやGIF、JPGが利用可能です。 700x335pxまで縮小されます
locked: フォロワーを手動で承認する必要があります
note: あと%{count}文字入力できます。
@@ -18,6 +19,10 @@ ja:
user:
filtered_languages: 選択した言語があなたの公開タイムラインから取り除かれます
labels:
+ account:
+ fields:
+ name: ラベル
+ value: 内容
defaults:
avatar: アイコン
confirm_new_password: 新しいパスワード(確認用)
@@ -27,6 +32,7 @@ ja:
display_name: 表示名
email: メールアドレス
expires_in: 有効期限
+ fields: プロフィール補足情報
filtered_languages: 除外する言語
header: ヘッダー
locale: 言語
@@ -46,7 +52,7 @@ ja:
setting_reduce_motion: アニメーションの動きを減らす
setting_system_font_ui: システムのデフォルトフォントを使う
setting_theme: サイトテーマ
- setting_unfollow_modal: フォロー解除する前に確認ダイアログを表示する
+ setting_unfollow_modal: フォローを解除する前に確認ダイアログを表示する
severity: 重大性
type: インポートする項目
username: ユーザー名
diff --git a/config/locales/simple_form.ko.yml b/config/locales/simple_form.ko.yml
index 85eccf091..ccb05fd25 100644
--- a/config/locales/simple_form.ko.yml
+++ b/config/locales/simple_form.ko.yml
@@ -8,6 +8,7 @@ ko:
display_name:
one: 1 글자 남음
other: %{count} 글자 남음
+ fields: 당신의 프로파일에 최대 4개까지 표 형식으로 나타낼 수 있습니다
header: PNG, GIF 혹은 JPG. 최대 2MB. 700x335px로 다운스케일 됨
locked: 수동으로 팔로워를 승인하고, 기본 툿 프라이버시 설정을 팔로워 전용으로 변경
note:
@@ -22,6 +23,10 @@ ko:
user:
filtered_languages: 선택된 언어가 공개 타임라인에서 제외 될 것입니다
labels:
+ account:
+ fields:
+ name: 라벨
+ value: 내용
defaults:
avatar: 아바타
confirm_new_password: 새로운 비밀번호 다시 입력
@@ -31,6 +36,7 @@ ko:
display_name: 표시되는 이름
email: 이메일 주소
expires_in: 만료시각
+ fields: 프로필 메타데이터
filtered_languages: 숨긴 언어들
header: 헤더
locale: 언어
diff --git a/config/locales/simple_form.nl.yml b/config/locales/simple_form.nl.yml
index 9876230b3..ec42adfd7 100644
--- a/config/locales/simple_form.nl.yml
+++ b/config/locales/simple_form.nl.yml
@@ -8,6 +8,7 @@ nl:
display_name:
one: 1 teken over
other: %{count} tekens over
+ fields: Je kan maximaal 4 items als een tabel op je profiel weergeven
header: PNG, GIF of JPG. Maximaal 2MB. Wordt teruggeschaald naar 700x335px
locked: Vereist dat je handmatig volgers moet accepteren
note:
@@ -22,6 +23,10 @@ nl:
user:
filtered_languages: De geselecteerde talen worden uit de lokale en globale tijdlijn verwijderd
labels:
+ account:
+ fields:
+ name: Label
+ value: Inhoud
defaults:
avatar: Avatar
confirm_new_password: Nieuw wachtwoord bevestigen
@@ -31,6 +36,7 @@ nl:
display_name: Weergavenaam
email: E-mailadres
expires_in: Vervalt na
+ fields: Metadata profiel
filtered_languages: Talen filteren
header: Omslagfoto
locale: Taal
@@ -63,7 +69,7 @@ nl:
digest: Periodiek e-mails met een samenvatting versturen
favourite: Een e-mail versturen wanneer iemand jouw toot als favoriet markeert
follow: Een e-mail versturen wanneer iemand jou volgt
- follow_request: Een e-mail versturen wanneer iemand jou wilt volgen
+ follow_request: Een e-mail versturen wanneer iemand jou wil volgen
mention: Een e-mail versturen wanneer iemand jou vermeld
reblog: Een e-mail versturen wanneer iemand jouw toot heeft geboost
'no': Nee
diff --git a/config/locales/simple_form.sk.yml b/config/locales/simple_form.sk.yml
index e504c9774..f928fd6a9 100644
--- a/config/locales/simple_form.sk.yml
+++ b/config/locales/simple_form.sk.yml
@@ -8,6 +8,7 @@ sk:
display_name:
one: Ostáva ti 1 znak
other: Ostáva ti %{count} znakov
+ fields: Môžeš mať 4 položky na svojom profile zobrazené vo forme tabuľky
header: PNG, GIF alebo JPG. Maximálne 2MB. Bude zmenšený na 700x335px
locked: Musíte manuálne schváliť sledujúcich
note:
@@ -22,6 +23,10 @@ sk:
user:
filtered_languages: Zaškrtnuté jazyky budú pre teba vynechané nebudú z verejnej časovej osi
labels:
+ account:
+ fields:
+ name: Označenie
+ value: Obsah
defaults:
avatar: Avatar
confirm_new_password: Opäť vaše nové heslo pre potvrdenie
@@ -31,6 +36,7 @@ sk:
display_name: Meno
email: Emailová adresa
expires_in: Expirovať po
+ fields: Metadáta profilu
filtered_languages: Filtrované jazyky
header: Obrázok v hlavičke
locale: Jazyk
@@ -43,9 +49,9 @@ sk:
setting_auto_play_gif: Automaticky prehrávať animované GIFy
setting_boost_modal: Zobrazovať potvrdzovacie okno pred re-toot
setting_default_privacy: Nastavenie súkromia príspevkov
- setting_default_sensitive: Označiť každý obrázok/video/súbor ako chúlostivý
- setting_delete_modal: Zobrazovať potvrdzovacie okno pred zmazaním toot-u
- setting_display_sensitive_media: Vždy zobrazovať médiá označované ako senzitívne
+ setting_default_sensitive: Označ všetky mediálne súbory ako chúlostivé
+ setting_delete_modal: Zobrazuj potvrdzovacie okno pred vymazaním toot-u
+ setting_display_sensitive_media: Vždy zobraz médiá označené ako chúlostivé
setting_noindex: Nezaraďuj príspevky do indexu pre vyhľadávče
setting_reduce_motion: Redukovať pohyb v animáciách
setting_system_font_ui: Použiť základné systémové písmo
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index 37f711323..a38b245b3 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -4,6 +4,7 @@ sk:
about_hashtag_html: Toto sú verejné toot príspevky otagované #%{tagom}. Ak máš účet niekde vo fediverse, môžeš ich používať.
about_mastodon_html: Mastodon je sociálna sieť založená na otvorených webových protokoloch. Jej zrojový kód je otvorený a je decentralizovaná podobne ako email.
about_this: O tejto instancii
+ administered_by: 'Správca je:'
closed_registrations: Registrácie sú momentálne uzatvorené. Avšak, môžeš nájsť nejaký iný Mastodon server kde si založ účet a získaj tak prístup do presne tej istej siete, odtiaľ.
contact: Kontakt
contact_missing: Nezadané
@@ -60,7 +61,15 @@ sk:
destroyed_msg: Poznámka moderátora bola úspešne zmazaná!
accounts:
are_you_sure: Ste si istý?
+ avatar: Maskot
by_domain: Doména
+ change_email:
+ changed_msg: Email k tomuto účtu bol úspešne zmenený!
+ current_email: Súčastný email
+ label: Zmeniť email
+ new_email: Nový email
+ submit: Zmeniť email
+ title: Zmeň email pre %{username}
confirm: Potvrdiť
confirmed: Potvrdený
demote: Degradovať
@@ -108,6 +117,7 @@ sk:
public: Verejná os
push_subscription_expires: PuSH odoberanie expiruje
redownload: Obnoviť avatar
+ remove_avatar: Odstrániť avatár
reset: Reset
reset_password: Obnoviť heslo
resubscribe: Znovu odoberať
@@ -128,6 +138,7 @@ sk:
statuses: Príspevky
subscribe: Odoberať
title: Účty
+ unconfirmed_email: Nepotvrdený email
undo_silenced: Zrušiť stíšenie
undo_suspension: Zrušiť suspendáciu
unsubscribe: Prestať odoberať
@@ -150,8 +161,9 @@ sk:
enable_user: "%{name} povolil prihlásenie pre používateľa %{target}"
memorialize_account: '%{name} zmenil účet %{target} na stránku "Navždy budeme spomínať"'
promote_user: "%{name} povýšil/a používateľa %{target}"
+ remove_avatar_user: "%{name} odstránil/a %{target}ov avatár"
reset_password_user: "%{name} resetoval/a heslo pre používateľa %{target}"
- resolve_report: "%{name} zamietli nahlásenie %{target}"
+ resolve_report: "%{name} vyriešili nahlásenie užívateľa %{target}"
silence_account: "%{name} utíšil/a účet %{target}"
suspend_account: "%{name} zablokoval/a účet používateľa %{target}"
unsilence_account: "%{name} zrušil/a utíšenie účtu používateľa %{target}"
@@ -239,8 +251,14 @@ sk:
expired: Expirované
title: Filtrovať
title: Pozvánky
+ report_notes:
+ created_msg: Poznámka o nahlásení úspešne vytvorená!
+ destroyed_msg: Poznámka o nahlásení úspešne vymazaná!
reports:
- action_taken_by: Zákrok vykonal
+ account:
+ note: poznámka
+ report: nahlás
+ action_taken_by: Zákrok vykonal/a
are_you_sure: Ste si istý/á?
comment:
none: Žiadne
From bfc41711dd5b9725d135c11807aa645ebc78bc18 Mon Sep 17 00:00:00 2001
From: Stefan Midjich
Date: Wed, 25 Apr 2018 01:54:24 +0200
Subject: [PATCH 146/442] =?UTF-8?q?more=20sane=20phrasing=20in=20?=
=?UTF-8?q?=F0=9F=87=B8=F0=9F=87=AA=20translation=20(#7256)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* more sane phrasing in 🇸🇪 translation
* another small issue in 🇸🇪 translation
---
config/locales/sv.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 7e763c2aa..993bdd909 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -9,7 +9,7 @@ sv:
contact_missing: Inte inställd
contact_unavailable: N/A
description_headline: Vad är %{domain}?
- domain_count_after: annan instans
+ domain_count_after: andra instanser
domain_count_before: Uppkopplad mot
extended_description_html: |
En bra plats för regler
@@ -29,7 +29,7 @@ sv:
other_instances: Instanslista
source_code: Källkod
status_count_after: statusar
- status_count_before: Vem författade
+ status_count_before: Som skapat
user_count_after: användare
user_count_before: Hem till
what_is_mastodon: Vad är Mastodon?
From 9d4710ed0059b2f789e6b32b9f81d4ce90b98907 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Wed, 25 Apr 2018 02:10:02 +0200
Subject: [PATCH 147/442] Add RSS feeds for end-users (#7259)
* Add RSS feed for accounts
* Add RSS feeds for hashtags
* Fix code style issues
* Fix code style issues
---
app/controllers/accounts_controller.rb | 10 +-
app/controllers/tags_controller.rb | 11 +-
app/helpers/stream_entries_helper.rb | 12 +-
app/lib/rss_builder.rb | 130 ++++++++++++++++++++++
app/serializers/rss/account_serializer.rb | 39 +++++++
app/serializers/rss/tag_serializer.rb | 37 ++++++
6 files changed, 230 insertions(+), 9 deletions(-)
create mode 100644 app/lib/rss_builder.rb
create mode 100644 app/serializers/rss/account_serializer.rb
create mode 100644 app/serializers/rss/tag_serializer.rb
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 7bf35825f..1152d4aca 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -20,9 +20,10 @@ class AccountsController < ApplicationController
@pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses?
@statuses = filtered_status_page(params)
@statuses = cache_collection(@statuses, Status)
+
unless @statuses.empty?
- @older_url = older_url if @statuses.last.id > filtered_statuses.last.id
- @newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
+ @older_url = older_url if @statuses.last.id > filtered_statuses.last.id
+ @newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
end
end
@@ -31,6 +32,11 @@ class AccountsController < ApplicationController
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? }))
end
+ format.rss do
+ @statuses = cache_collection(default_statuses.without_reblogs.without_replies.limit(PAGE_SIZE), Status)
+ render xml: RSS::AccountSerializer.render(@account, @statuses)
+ end
+
format.json do
skip_session!
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 9f3090e37..014a5c9b8 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class TagsController < ApplicationController
+ PAGE_SIZE = 20
+
before_action :set_body_classes
before_action :set_instance_presenter
@@ -13,8 +15,15 @@ class TagsController < ApplicationController
@initial_state_json = serializable_resource.to_json
end
+ format.rss do
+ @statuses = Status.as_tag_timeline(@tag).limit(PAGE_SIZE)
+ @statuses = cache_collection(@statuses, Status)
+
+ render xml: RSS::TagSerializer.render(@tag, @statuses)
+ end
+
format.json do
- @statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id])
+ @statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(PAGE_SIZE, params[:max_id])
@statuses = cache_collection(@statuses, Status)
render json: collection_presenter,
diff --git a/app/helpers/stream_entries_helper.rb b/app/helpers/stream_entries_helper.rb
index 8254ef4dc..c6f12ecd4 100644
--- a/app/helpers/stream_entries_helper.rb
+++ b/app/helpers/stream_entries_helper.rb
@@ -12,17 +12,17 @@ module StreamEntriesHelper
prepend_str = [
[
number_to_human(account.statuses_count, strip_insignificant_zeros: true),
- t('accounts.posts'),
+ I18n.t('accounts.posts'),
].join(' '),
[
number_to_human(account.following_count, strip_insignificant_zeros: true),
- t('accounts.following'),
+ I18n.t('accounts.following'),
].join(' '),
[
number_to_human(account.followers_count, strip_insignificant_zeros: true),
- t('accounts.followers'),
+ I18n.t('accounts.followers'),
].join(' '),
].join(', ')
@@ -40,16 +40,16 @@ module StreamEntriesHelper
end
end
- text = attachments.to_a.reject { |_, value| value.zero? }.map { |key, value| t("statuses.attached.#{key}", count: value) }.join(' · ')
+ text = attachments.to_a.reject { |_, value| value.zero? }.map { |key, value| I18n.t("statuses.attached.#{key}", count: value) }.join(' · ')
return if text.blank?
- t('statuses.attached.description', attached: text)
+ I18n.t('statuses.attached.description', attached: text)
end
def status_text_summary(status)
return if status.spoiler_text.blank?
- t('statuses.content_warning', warning: status.spoiler_text)
+ I18n.t('statuses.content_warning', warning: status.spoiler_text)
end
def status_description(status)
diff --git a/app/lib/rss_builder.rb b/app/lib/rss_builder.rb
new file mode 100644
index 000000000..63ddba2e8
--- /dev/null
+++ b/app/lib/rss_builder.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+class RSSBuilder
+ class ItemBuilder
+ def initialize
+ @item = Ox::Element.new('item')
+ end
+
+ def title(str)
+ @item << (Ox::Element.new('title') << str)
+
+ self
+ end
+
+ def link(str)
+ @item << Ox::Element.new('guid').tap do |guid|
+ guid['isPermalink'] = 'true'
+ guid << str
+ end
+
+ @item << (Ox::Element.new('link') << str)
+
+ self
+ end
+
+ def pub_date(date)
+ @item << (Ox::Element.new('pubDate') << date.to_formatted_s(:rfc822))
+
+ self
+ end
+
+ def description(str)
+ @item << (Ox::Element.new('description') << str)
+
+ self
+ end
+
+ def enclosure(url, type, size)
+ @item << Ox::Element.new('enclosure').tap do |enclosure|
+ enclosure['url'] = url
+ enclosure['length'] = size
+ enclosure['type'] = type
+ end
+
+ self
+ end
+
+ def to_element
+ @item
+ end
+ end
+
+ def initialize
+ @document = Ox::Document.new(version: '1.0')
+ @channel = Ox::Element.new('channel')
+
+ @document << (rss << @channel)
+ end
+
+ def title(str)
+ @channel << (Ox::Element.new('title') << str)
+
+ self
+ end
+
+ def link(str)
+ @channel << (Ox::Element.new('link') << str)
+
+ self
+ end
+
+ def image(str)
+ @channel << Ox::Element.new('image').tap do |image|
+ image << (Ox::Element.new('url') << str)
+ image << (Ox::Element.new('title') << '')
+ image << (Ox::Element.new('link') << '')
+ end
+
+ @channel << (Ox::Element.new('webfeeds:icon') << str)
+
+ self
+ end
+
+ def cover(str)
+ @channel << Ox::Element.new('webfeeds:cover').tap do |cover|
+ cover['image'] = str
+ end
+
+ self
+ end
+
+ def logo(str)
+ @channel << (Ox::Element.new('webfeeds:logo') << str)
+
+ self
+ end
+
+ def accent_color(str)
+ @channel << (Ox::Element.new('webfeeds:accentColor') << str)
+
+ self
+ end
+
+ def description(str)
+ @channel << (Ox::Element.new('description') << str)
+
+ self
+ end
+
+ def item
+ @channel << ItemBuilder.new.tap do |item|
+ yield item
+ end.to_element
+
+ self
+ end
+
+ def to_xml
+ ('' + Ox.dump(@document, effort: :tolerant)).force_encoding('UTF-8')
+ end
+
+ private
+
+ def rss
+ Ox::Element.new('rss').tap do |rss|
+ rss['version'] = '2.0'
+ rss['xmlns:webfeeds'] = 'http://webfeeds.org/rss/1.0'
+ end
+ end
+end
diff --git a/app/serializers/rss/account_serializer.rb b/app/serializers/rss/account_serializer.rb
new file mode 100644
index 000000000..bde360a41
--- /dev/null
+++ b/app/serializers/rss/account_serializer.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+class RSS::AccountSerializer
+ include ActionView::Helpers::NumberHelper
+ include StreamEntriesHelper
+ include RoutingHelper
+
+ def render(account, statuses)
+ builder = RSSBuilder.new
+
+ builder.title("#{display_name(account)} (@#{account.local_username_and_domain})")
+ .description(account_description(account))
+ .link(TagManager.instance.url_for(account))
+ .logo(full_asset_url(asset_pack_path('logo.svg')))
+ .accent_color('2b90d9')
+
+ builder.image(full_asset_url(account.avatar.url(:original))) if account.avatar?
+ builder.cover(full_asset_url(account.header.url(:original))) if account.header?
+
+ statuses.each do |status|
+ builder.item do |item|
+ item.title(status.title)
+ .link(TagManager.instance.url_for(status))
+ .pub_date(status.created_at)
+ .description(status.spoiler_text.presence || Formatter.instance.format(status).to_str)
+
+ status.media_attachments.each do |media|
+ item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, length: media.file.size)
+ end
+ end
+ end
+
+ builder.to_xml
+ end
+
+ def self.render(account, statuses)
+ new.render(account, statuses)
+ end
+end
diff --git a/app/serializers/rss/tag_serializer.rb b/app/serializers/rss/tag_serializer.rb
new file mode 100644
index 000000000..7680a8da5
--- /dev/null
+++ b/app/serializers/rss/tag_serializer.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class RSS::TagSerializer
+ include ActionView::Helpers::NumberHelper
+ include ActionView::Helpers::SanitizeHelper
+ include StreamEntriesHelper
+ include RoutingHelper
+
+ def render(tag, statuses)
+ builder = RSSBuilder.new
+
+ builder.title("##{tag.name}")
+ .description(strip_tags(I18n.t('about.about_hashtag_html', hashtag: tag.name)))
+ .link(tag_url(tag))
+ .logo(full_asset_url(asset_pack_path('logo.svg')))
+ .accent_color('2b90d9')
+
+ statuses.each do |status|
+ builder.item do |item|
+ item.title(status.title)
+ .link(TagManager.instance.url_for(status))
+ .pub_date(status.created_at)
+ .description(status.spoiler_text.presence || Formatter.instance.format(status).to_str)
+
+ status.media_attachments.each do |media|
+ item.enclosure(full_asset_url(media.file.url(:original, false)), media.file.content_type, length: media.file.size)
+ end
+ end
+ end
+
+ builder.to_xml
+ end
+
+ def self.render(tag, statuses)
+ new.render(tag, statuses)
+ end
+end
From f58dcbc9814b5ba2fd4f7d7af643aa25dcf40594 Mon Sep 17 00:00:00 2001
From: MIYAGI Hikaru
Date: Wed, 25 Apr 2018 09:14:49 +0900
Subject: [PATCH 148/442] HTTP proxy support for outgoing request, manage
access to hidden service (#7134)
* Add support for HTTP client proxy
* Add access control for darknet
Supress error when access to darknet via transparent proxy
* Fix the codes pointed out
* Lint
* Fix an omission + lint
* any? -> include?
* Change detection method to regexp to avoid test fail
---
.env.production.sample | 7 +++++++
app/lib/request.rb | 16 +++++++++++++++-
config/initializers/http_client_proxy.rb | 24 ++++++++++++++++++++++++
3 files changed, 46 insertions(+), 1 deletion(-)
create mode 100644 config/initializers/http_client_proxy.rb
diff --git a/.env.production.sample b/.env.production.sample
index 9de2c0650..c936546da 100644
--- a/.env.production.sample
+++ b/.env.production.sample
@@ -214,3 +214,10 @@ STREAMING_CLUSTER_NUM=1
# SAML_UID_ATTRIBUTE="urn:oid:0.9.2342.19200300.100.1.1"
# SAML_ATTRIBUTES_STATEMENTS_VERIFIED=
# SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL=
+
+# Use HTTP proxy for outgoing request (optional)
+# http_proxy=http://gateway.local:8118
+# Access control for hidden service.
+# ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
+# If you use transparent proxy to access to hidden service, uncomment following for skipping private address check.
+# HIDDEN_SERVICE_VIA_TRANSPARENT_PROXY=true
diff --git a/app/lib/request.rb b/app/lib/request.rb
index dca93a6e9..0acd654da 100644
--- a/app/lib/request.rb
+++ b/app/lib/request.rb
@@ -11,9 +11,10 @@ class Request
def initialize(verb, url, **options)
@verb = verb
@url = Addressable::URI.parse(url).normalize
- @options = options.merge(socket_class: Socket)
+ @options = options.merge(use_proxy? ? Rails.configuration.x.http_client_proxy : { socket_class: Socket })
@headers = {}
+ raise Mastodon::HostValidationError, 'Instance does not support hidden service connections' if block_hidden_service?
set_common_headers!
set_digest! if options.key?(:body)
end
@@ -99,6 +100,14 @@ class Request
@http_client ||= HTTP.timeout(:per_operation, timeout).follow(max_hops: 2)
end
+ def use_proxy?
+ Rails.configuration.x.http_client_proxy.present?
+ end
+
+ def block_hidden_service?
+ !Rails.configuration.x.access_to_hidden_service && /\.(onion|i2p)$/.match(@url.host)
+ end
+
module ClientLimit
def body_with_limit(limit = 1.megabyte)
raise Mastodon::LengthValidationError if content_length.present? && content_length > limit
@@ -129,6 +138,7 @@ class Request
class Socket < TCPSocket
class << self
def open(host, *args)
+ return super host, *args if thru_hidden_service? host
outer_e = nil
Addrinfo.foreach(host, nil, nil, :SOCK_STREAM) do |address|
begin
@@ -142,6 +152,10 @@ class Request
end
alias new open
+
+ def thru_hidden_service?(host)
+ Rails.configuration.x.hidden_service_via_transparent_proxy && /\.(onion|i2p)$/.match(host)
+ end
end
end
diff --git a/config/initializers/http_client_proxy.rb b/config/initializers/http_client_proxy.rb
new file mode 100644
index 000000000..f5026d59e
--- /dev/null
+++ b/config/initializers/http_client_proxy.rb
@@ -0,0 +1,24 @@
+Rails.application.configure do
+ config.x.http_client_proxy = {}
+ if ENV['http_proxy'].present?
+ proxy = URI.parse(ENV['http_proxy'])
+ raise "Unsupported proxy type: #{proxy.scheme}" unless %w(http https).include? proxy.scheme
+ raise "No proxy host" unless proxy.host
+
+ host = proxy.host
+ host = host[1...-1] if host[0] == '[' #for IPv6 address
+ config.x.http_client_proxy[:proxy] = { proxy_address: host, proxy_port: proxy.port, proxy_username: proxy.user, proxy_password: proxy.password }.compact
+ end
+
+ config.x.access_to_hidden_service = ENV['ALLOW_ACCESS_TO_HIDDEN_SERVICE'] == 'true'
+ config.x.hidden_service_via_transparent_proxy = ENV['HIDDEN_SERVICE_VIA_TRANSPARENT_PROXY'] == 'true'
+end
+
+module Goldfinger
+ def self.finger(uri, opts = {})
+ to_hidden = /\.(onion|i2p)(:\d+)?$/.match(uri)
+ raise Mastodon::HostValidationError, 'Instance does not support hidden service connections' if !Rails.configuration.x.access_to_hidden_service && to_hidden
+ opts = opts.merge(Rails.configuration.x.http_client_proxy).merge(ssl: !to_hidden)
+ Goldfinger::Client.new(uri, opts).finger
+ end
+end
From eb593a5a0c9ee9749115f867a5675ceb1f231379 Mon Sep 17 00:00:00 2001
From: MIYAGI Hikaru
Date: Wed, 25 Apr 2018 21:12:28 +0900
Subject: [PATCH 149/442] Append '.test' to hostname in stub data (#7260)
---
spec/fixtures/requests/oembed_json.html | 2 +-
spec/fixtures/requests/oembed_json_xml.html | 4 +-
spec/fixtures/requests/oembed_xml.html | 2 +-
spec/helpers/jsonld_helper_spec.rb | 24 ++++++------
spec/lib/formatter_spec.rb | 6 +--
spec/lib/ostatus/atom_serializer_spec.rb | 26 ++++++-------
spec/lib/provider_discovery_spec.rb | 38 +++++++++----------
spec/lib/tag_manager_spec.rb | 34 ++++++++---------
spec/models/account_spec.rb | 10 ++---
spec/models/status_pin_spec.rb | 2 +-
.../process_account_service_spec.rb | 4 +-
11 files changed, 76 insertions(+), 76 deletions(-)
diff --git a/spec/fixtures/requests/oembed_json.html b/spec/fixtures/requests/oembed_json.html
index 773a4f92a..167085871 100644
--- a/spec/fixtures/requests/oembed_json.html
+++ b/spec/fixtures/requests/oembed_json.html
@@ -1,7 +1,7 @@
-
+
diff --git a/spec/fixtures/requests/oembed_json_xml.html b/spec/fixtures/requests/oembed_json_xml.html
index 8afd8e997..9f5b9e8be 100644
--- a/spec/fixtures/requests/oembed_json_xml.html
+++ b/spec/fixtures/requests/oembed_json_xml.html
@@ -7,8 +7,8 @@
> The type attribute must contain either application/json+oembed for JSON
> responses, or text/xml+oembed for XML.
-->
-
-
+
+