+ );
+};
diff --git a/app/javascript/mastodon/features/account_timeline/index.jsx b/app/javascript/mastodon/features/account_timeline/index.jsx
index 5dae66b463..5ec029593d 100644
--- a/app/javascript/mastodon/features/account_timeline/index.jsx
+++ b/app/javascript/mastodon/features/account_timeline/index.jsx
@@ -21,7 +21,7 @@ import { LoadingIndicator } from '../../components/loading_indicator';
import StatusList from '../../components/status_list';
import Column from '../ui/components/column';
-import LimitedAccountHint from './components/limited_account_hint';
+import { LimitedAccountHint } from './components/limited_account_hint';
import HeaderContainer from './containers/header_container';
const emptyList = ImmutableList();
diff --git a/app/javascript/mastodon/features/compose/components/action_bar.jsx b/app/javascript/mastodon/features/compose/components/action_bar.jsx
index f7488cf554..3e21090925 100644
--- a/app/javascript/mastodon/features/compose/components/action_bar.jsx
+++ b/app/javascript/mastodon/features/compose/components/action_bar.jsx
@@ -28,7 +28,7 @@ const messages = defineMessages({
class ActionBar extends PureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
onLogout: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
diff --git a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
index ebda0590e3..0a73bc1020 100644
--- a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
+++ b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
@@ -7,7 +7,7 @@ import { DisplayName } from '../../../components/display_name';
export default class AutosuggestAccount extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
};
render () {
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.jsx b/app/javascript/mastodon/features/compose/components/compose_form.jsx
index 5bd990a302..3b752f252d 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
+import { createRef } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
@@ -80,6 +81,11 @@ class ComposeForm extends ImmutablePureComponent {
highlighted: false,
};
+ constructor(props) {
+ super(props);
+ this.textareaRef = createRef(null);
+ }
+
handleChange = (e) => {
this.props.onChange(e.target.value);
};
@@ -103,10 +109,10 @@ class ComposeForm extends ImmutablePureComponent {
};
handleSubmit = (e) => {
- if (this.props.text !== this.autosuggestTextarea.textarea.value) {
+ if (this.props.text !== this.textareaRef.current.value) {
// Something changed the text inside the textarea (e.g. browser extensions like Grammarly)
// Update the state to match the current text
- this.props.onChange(this.autosuggestTextarea.textarea.value);
+ this.props.onChange(this.textareaRef.current.value);
}
if (!this.canSubmit()) {
@@ -185,26 +191,22 @@ class ComposeForm extends ImmutablePureComponent {
// immediately selectable, we have to wait for observers to run, as
// described in https://github.com/WICG/inert#performance-and-gotchas
Promise.resolve().then(() => {
- this.autosuggestTextarea.textarea.setSelectionRange(selectionStart, selectionEnd);
- this.autosuggestTextarea.textarea.focus();
+ this.textareaRef.current.setSelectionRange(selectionStart, selectionEnd);
+ this.textareaRef.current.focus();
this.setState({ highlighted: true });
this.timeout = setTimeout(() => this.setState({ highlighted: false }), 700);
}).catch(console.error);
} else if(prevProps.isSubmitting && !this.props.isSubmitting) {
- this.autosuggestTextarea.textarea.focus();
+ this.textareaRef.current.focus();
} else if (this.props.spoiler !== prevProps.spoiler) {
if (this.props.spoiler) {
this.spoilerText.input.focus();
} else if (prevProps.spoiler) {
- this.autosuggestTextarea.textarea.focus();
+ this.textareaRef.current.focus();
}
}
};
- setAutosuggestTextarea = (c) => {
- this.autosuggestTextarea = c;
- };
-
setSpoilerText = (c) => {
this.spoilerText = c;
};
@@ -215,7 +217,7 @@ class ComposeForm extends ImmutablePureComponent {
handleEmojiPick = (data) => {
const { text } = this.props;
- const position = this.autosuggestTextarea.textarea.selectionStart;
+ const position = this.textareaRef.current.selectionStart;
const needsSpace = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1]);
this.props.onPickEmoji(position, data, needsSpace);
@@ -264,7 +266,7 @@ class ComposeForm extends ImmutablePureComponent {
({
class AccountCard extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
intl: PropTypes.object.isRequired,
onFollow: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
index b5dfe510e9..ca2b454143 100644
--- a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
+++ b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
@@ -22,7 +22,7 @@ const messages = defineMessages({
class AccountAuthorize extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
onAuthorize: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/followers/index.jsx b/app/javascript/mastodon/features/followers/index.jsx
index fc0ce8ab30..e50b2171a0 100644
--- a/app/javascript/mastodon/features/followers/index.jsx
+++ b/app/javascript/mastodon/features/followers/index.jsx
@@ -23,7 +23,7 @@ import { ColumnBackButton } from '../../components/column_back_button';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
-import LimitedAccountHint from '../account_timeline/components/limited_account_hint';
+import { LimitedAccountHint } from '../account_timeline/components/limited_account_hint';
import HeaderContainer from '../account_timeline/containers/header_container';
import Column from '../ui/components/column';
diff --git a/app/javascript/mastodon/features/following/index.jsx b/app/javascript/mastodon/features/following/index.jsx
index fb02d17950..73e77aadd7 100644
--- a/app/javascript/mastodon/features/following/index.jsx
+++ b/app/javascript/mastodon/features/following/index.jsx
@@ -23,7 +23,7 @@ import { ColumnBackButton } from '../../components/column_back_button';
import { LoadingIndicator } from '../../components/loading_indicator';
import ScrollableList from '../../components/scrollable_list';
import AccountContainer from '../../containers/account_container';
-import LimitedAccountHint from '../account_timeline/components/limited_account_hint';
+import { LimitedAccountHint } from '../account_timeline/components/limited_account_hint';
import HeaderContainer from '../account_timeline/containers/header_container';
import Column from '../ui/components/column';
diff --git a/app/javascript/mastodon/features/list_adder/components/account.jsx b/app/javascript/mastodon/features/list_adder/components/account.jsx
index 31a2e96379..94a90726e3 100644
--- a/app/javascript/mastodon/features/list_adder/components/account.jsx
+++ b/app/javascript/mastodon/features/list_adder/components/account.jsx
@@ -21,7 +21,7 @@ const makeMapStateToProps = () => {
class Account extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
};
render () {
diff --git a/app/javascript/mastodon/features/list_editor/components/account.jsx b/app/javascript/mastodon/features/list_editor/components/account.jsx
index f38c7d93a7..18d5e905cb 100644
--- a/app/javascript/mastodon/features/list_editor/components/account.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/account.jsx
@@ -39,7 +39,7 @@ const mapDispatchToProps = (dispatch, { accountId }) => ({
class Account extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
intl: PropTypes.object.isRequired,
onRemove: PropTypes.func.isRequired,
onAdd: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/follow_request.jsx b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
index c10633beeb..03420b6c01 100644
--- a/app/javascript/mastodon/features/notifications/components/follow_request.jsx
+++ b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
@@ -22,7 +22,7 @@ const messages = defineMessages({
class FollowRequest extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
onAuthorize: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/report.jsx b/app/javascript/mastodon/features/notifications/components/report.jsx
index cb50b62cdc..52d6bfee9d 100644
--- a/app/javascript/mastodon/features/notifications/components/report.jsx
+++ b/app/javascript/mastodon/features/notifications/components/report.jsx
@@ -20,7 +20,7 @@ const messages = defineMessages({
class Report extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
report: ImmutablePropTypes.map.isRequired,
hidden: PropTypes.bool,
intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/onboarding/index.jsx b/app/javascript/mastodon/features/onboarding/index.jsx
index 7b8a41faa5..51d4b71f24 100644
--- a/app/javascript/mastodon/features/onboarding/index.jsx
+++ b/app/javascript/mastodon/features/onboarding/index.jsx
@@ -46,7 +46,7 @@ const mapStateToProps = () => {
class Onboarding extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
- account: ImmutablePropTypes.map,
+ account: ImmutablePropTypes.record,
...WithRouterPropTypes,
};
diff --git a/app/javascript/mastodon/features/onboarding/share.jsx b/app/javascript/mastodon/features/onboarding/share.jsx
index 8e01701eb3..3349244223 100644
--- a/app/javascript/mastodon/features/onboarding/share.jsx
+++ b/app/javascript/mastodon/features/onboarding/share.jsx
@@ -145,7 +145,7 @@ class Share extends PureComponent {
static propTypes = {
onBack: PropTypes.func,
- account: ImmutablePropTypes.map,
+ account: ImmutablePropTypes.record,
intl: PropTypes.object,
};
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
index b7fd9d1276..80a13bd2e3 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
@@ -27,7 +27,7 @@ class Header extends ImmutablePureComponent {
static propTypes = {
accountId: PropTypes.string.isRequired,
statusId: PropTypes.string.isRequired,
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
diff --git a/app/javascript/mastodon/features/report/thanks.jsx b/app/javascript/mastodon/features/report/thanks.jsx
index 146d4b3897..904c447701 100644
--- a/app/javascript/mastodon/features/report/thanks.jsx
+++ b/app/javascript/mastodon/features/report/thanks.jsx
@@ -20,7 +20,7 @@ class Thanks extends PureComponent {
static propTypes = {
submitted: PropTypes.bool,
onClose: PropTypes.func.isRequired,
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
dispatch: PropTypes.func.isRequired,
};
diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
index 40481e2c87..5353ebdb8a 100644
--- a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
@@ -110,7 +110,7 @@ class FocalPointModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.map.isRequired,
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
isUploadingThumbnail: PropTypes.bool,
onSave: PropTypes.func.isRequired,
onChangeDescription: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/report_modal.jsx b/app/javascript/mastodon/features/ui/components/report_modal.jsx
index 2b6f04207e..3fd8ff127d 100644
--- a/app/javascript/mastodon/features/ui/components/report_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/report_modal.jsx
@@ -41,7 +41,7 @@ class ReportModal extends ImmutablePureComponent {
statusId: PropTypes.string,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.record.isRequired,
};
state = {
diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js
index 3a59b33978..4f9c1f7378 100644
--- a/app/javascript/mastodon/initial_state.js
+++ b/app/javascript/mastodon/initial_state.js
@@ -1,43 +1,5 @@
// @ts-check
-/**
- * @typedef Emoji
- * @property {string} shortcode
- * @property {string} static_url
- * @property {string} url
- */
-
-/**
- * @typedef AccountField
- * @property {string} name
- * @property {string} value
- * @property {string} verified_at
- */
-
-/**
- * @typedef Account
- * @property {string} acct
- * @property {string} avatar
- * @property {string} avatar_static
- * @property {boolean} bot
- * @property {string} created_at
- * @property {boolean=} discoverable
- * @property {string} display_name
- * @property {Emoji[]} emojis
- * @property {AccountField[]} fields
- * @property {number} followers_count
- * @property {number} following_count
- * @property {boolean} group
- * @property {string} header
- * @property {string} header_static
- * @property {string} id
- * @property {string=} last_status_at
- * @property {boolean} locked
- * @property {string} note
- * @property {number} statuses_count
- * @property {string} url
- * @property {string} username
- */
/**
* @typedef {[code: string, name: string, localName: string]} InitialStateLanguage
@@ -87,7 +49,7 @@
/**
* @typedef InitialState
- * @property {Record} accounts
+ * @property {Record} accounts
* @property {InitialStateLanguage[]} languages
* @property {boolean=} critical_updates_pending
* @property {InitialStateMeta} meta
diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json
index a578920e70..f17aa54aa8 100644
--- a/app/javascript/mastodon/locales/de.json
+++ b/app/javascript/mastodon/locales/de.json
@@ -426,7 +426,7 @@
"notification.admin.sign_up": "{name} registrierte sich",
"notification.favourite": "{name} favorisierte deinen Beitrag",
"notification.reaction": "{name} hat auf deinen Beitrag reagiert",
- "notification.follow": "{name} folgt dir jetzt",
+ "notification.follow": "{name} folgt dir",
"notification.follow_request": "{name} möchte dir folgen",
"notification.mention": "{name} erwähnte dich",
"notification.own_poll": "Deine Umfrage ist beendet",
diff --git a/app/javascript/mastodon/locales/global_locale.ts b/app/javascript/mastodon/locales/global_locale.ts
index 2d4329c764..8d142b8b04 100644
--- a/app/javascript/mastodon/locales/global_locale.ts
+++ b/app/javascript/mastodon/locales/global_locale.ts
@@ -1,3 +1,5 @@
+import { isDevelopment } from 'mastodon/utils/environment';
+
export interface LocaleData {
locale: string;
messages: Record;
@@ -11,7 +13,7 @@ export function setLocale(locale: LocaleData) {
export function getLocale(): LocaleData {
if (!loadedLocale) {
- if (process.env.NODE_ENV === 'development') {
+ if (isDevelopment()) {
throw new Error('getLocale() called before any locale has been set');
} else {
return { locale: 'unknown', messages: {} };
diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json
index 59cdb69a6c..a8cb2ec276 100644
--- a/app/javascript/mastodon/locales/he.json
+++ b/app/javascript/mastodon/locales/he.json
@@ -202,7 +202,7 @@
"dismissable_banner.community_timeline": "אלו הם החצרוצים הציבוריים האחרונים מהמשתמשים על שרת {domain}.",
"dismissable_banner.dismiss": "בטל",
"dismissable_banner.explore_links": "אלו הקישורים האחרונים ששותפו על ידי משתמשים ששרת זה רואה ברשת המבוזרת כרגע.",
- "dismissable_banner.explore_statuses": "ההודעות האלו, משרת זה ואחרים ברשת המבוזרת, צוברים חשיפה היום. הודעות חדשות יותר עם יותר הדהודים וחיבובים מדורגים יותר לגובה.",
+ "dismissable_banner.explore_statuses": "אלו הודעות משרת זה ואחרים ברשת המבוזרת שצוברות חשיפה היום. הודעות חדשות יותר עם יותר הדהודים וחיבובים מדורגות גבוה יותר.",
"dismissable_banner.explore_tags": "התגיות האלו, משרת זה ואחרים ברשת המבוזרת, צוברות חשיפה כעת.",
"dismissable_banner.public_timeline": "אלו ההודעות האחרונות שהתקבלו מהמשתמשים שנעקבים על ידי משתמשים מ־{domain}.",
"embed.instructions": "ניתן להטמיע את ההודעה הזו באתרך ע\"י העתקת הקוד שלהלן.",
@@ -315,7 +315,7 @@
"home.pending_critical_update.title": "יצא עדכון אבטחה חשוב!",
"home.show_announcements": "הצג הכרזות",
"interaction_modal.description.favourite": "עם חשבון מסטודון, ניתן לחבב את ההודעה כדי לומר למחבר/ת שהערכת את תוכנו או כדי לשמור אותו לקריאה בעתיד.",
- "interaction_modal.description.follow": "עם חשבון מסטודון, ניתן לעקוב אחרי {name} כדי לקבל את הםוסטים שלו/ה בפיד הבית.",
+ "interaction_modal.description.follow": "עם חשבון מסטודון, ניתן לעקוב אחרי {name} כדי לקבל את הפוסטים שלו/ה בפיד הבית.",
"interaction_modal.description.reblog": "עם חשבון מסטודון, ניתן להדהד את החצרוץ ולשתף עם עוקבים.",
"interaction_modal.description.reply": "עם חשבון מסטודון, ניתן לענות לחצרוץ.",
"interaction_modal.login.action": "קח אותי לדף הבית",
@@ -349,7 +349,7 @@
"keyboard_shortcuts.hotkey": "מקש קיצור",
"keyboard_shortcuts.legend": "הצגת מקרא",
"keyboard_shortcuts.local": "פתיחת ציר זמן קהילתי",
- "keyboard_shortcuts.mention": "לאזכר את המחבר(ת)",
+ "keyboard_shortcuts.mention": "לאזכר את המחבר.ת",
"keyboard_shortcuts.muted": "פתיחת רשימת משתמשים מושתקים",
"keyboard_shortcuts.my_profile": "פתיחת הפרופיל שלך",
"keyboard_shortcuts.notifications": "פתיחת טור התראות",
@@ -493,7 +493,7 @@
"onboarding.steps.setup_profile.title": "התאמה אישית של הפרופיל",
"onboarding.steps.share_profile.body": "ספרו לחברים איך למצוא אתכם במסטודון!",
"onboarding.steps.share_profile.title": "לשתף פרופיל",
- "onboarding.tips.2fa": "הידעת? ניתן לאבטח את החשבון ע\"י הקמת אימות בשני צעדים במסך מאפייני החשבון. השיטה תעבוד עם כל יישומון תואם TOTP על המגשיר שלך, אין צורך לתת לנו את מספר הטלפון!",
+ "onboarding.tips.2fa": "הידעת? ניתן לאבטח את החשבון ע\"י הקמת אימות דו-שלבי במסך מאפייני החשבון. השיטה תעבוד עם כל יישומון תואם TOTP על המכשיר שלך, ללא צורך במספר טלפון!",
"onboarding.tips.accounts_from_other_servers": "הידעת? כיוון שמסטודון פועל ברשת מבוזרת, חלק מהפרופילים שתתקלו בהם פועלים משרתים אחרים משרת הבית שלכם. ניתן להיות איתם בקשר בצורה זהה לכל חשבון אחר! שם השרת שלהם הוא החלק השני של שם המשתמש שלהם!",
"onboarding.tips.migration": "הידעת? אם תחליטו כי {domain} איננו שרת שמתאים לכם בעתיד, ניתן לעבור לשרת אחר מבלי לאבד עוקבים. תוכלו אפילו להקים שרת משלכן!",
"onboarding.tips.verification": "הידעת? ניתן לאשרר את החשבון ע\"י קישור הפרופיל אל האתר שלכם ומהאתר חזרה לפרופיל. לא נדרשים תשלומים ומסמכים!",
@@ -575,7 +575,7 @@
"report.thanks.title": "לא מעוניין/ת לראות את זה?",
"report.thanks.title_actionable": "תודה על הדיווח, נבדוק את העניין.",
"report.unfollow": "הפסיקו לעקוב אחרי @{name}",
- "report.unfollow_explanation": "אתם עוקבים אחרי החשבון הזה. כדי להפסיק לראות את הפרסומים שלו בפיד הבית שלכם, הפסיקו לעקוב אחריהם.",
+ "report.unfollow_explanation": "אתם עוקבים אחרי החשבון הזה. כדי להפסיק לראות את הפרסומים שלו בפיד הבית שלכם, הפסיקו לעקוב אחריו.",
"report_notification.attached_statuses": "{count, plural, one {הודעה מצורפת} two {הודעותיים מצורפות} many {{count} הודעות מצורפות} other {{count} הודעות מצורפות}}",
"report_notification.categories.legal": "חוקי",
"report_notification.categories.other": "שונות",
@@ -630,7 +630,7 @@
"status.edited": "נערך ב{date}",
"status.edited_x_times": "נערך {count, plural, one {פעם {count}} other {{count} פעמים}}",
"status.embed": "הטמעה",
- "status.favourite": "מחובבת",
+ "status.favourite": "חיבוב",
"status.filter": "סנן הודעה זו",
"status.filtered": "סונן",
"status.hide": "הסתרת חיצרוץ",
@@ -707,7 +707,7 @@
"upload_modal.apply": "החל",
"upload_modal.applying": "מחיל…",
"upload_modal.choose_image": "בחר/י תמונה",
- "upload_modal.description_placeholder": "דג סקרן שט בים מאוכזב ולפתע מצא חברה",
+ "upload_modal.description_placeholder": "עטלף אבק נס דרך מזגן שהתפוצץ כי חם",
"upload_modal.detect_text": "זהה טקסט מתמונה",
"upload_modal.edit_media": "עריכת מדיה",
"upload_modal.hint": "הקליקי או גררי את המעגל על גבי התצוגה המקדימה על מנת לבחור בנקודת המוקד שתראה תמיד בכל התמונות הממוזערות.",
diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json
index 4d751cdda7..cb1b201a12 100644
--- a/app/javascript/mastodon/locales/hr.json
+++ b/app/javascript/mastodon/locales/hr.json
@@ -1,5 +1,6 @@
{
"about.contact": "Kontakt:",
+ "about.domain_blocks.no_reason_available": "Razlog nije dostupan",
"account.account_note_header": "Bilješka",
"account.add_or_remove_from_list": "Dodaj ili ukloni s liste",
"account.badges.bot": "Bot",
@@ -14,6 +15,7 @@
"account.edit_profile": "Uredi profil",
"account.enable_notifications": "Obavjesti me kada @{name} napravi objavu",
"account.endorse": "Istakni na profilu",
+ "account.featured_tags.last_status_never": "Nema postova",
"account.follow": "Prati",
"account.followers": "Pratitelji",
"account.followers.empty": "Nitko još ne prati korisnika/cu.",
@@ -21,13 +23,18 @@
"account.following_counter": "{count, plural, one {{counter} praćeni} few{{counter} praćena} other {{counter} praćenih}}",
"account.follows.empty": "Korisnik/ca još ne prati nikoga.",
"account.follows_you": "Prati te",
+ "account.go_to_profile": "Idi na profil",
"account.hide_reblogs": "Sakrij boostove od @{name}",
+ "account.in_memoriam": "U sjećanje.",
"account.link_verified_on": "Vlasništvo ove poveznice provjereno je {date}",
"account.locked_info": "Status privatnosti ovog računa postavljen je na zaključano. Vlasnik ručno pregledava tko ih može pratiti.",
"account.media": "Medijski sadržaj",
"account.mention": "Spomeni @{name}",
"account.mute": "Utišaj @{name}",
+ "account.mute_notifications_short": "Utišaj obavijesti",
+ "account.mute_short": "Utišaj",
"account.muted": "Utišano",
+ "account.open_original_page": "Otvori originalnu stranicu",
"account.posts": "Objave",
"account.posts_with_replies": "Objave i odgovori",
"account.report": "Prijavi @{name}",
@@ -52,6 +59,7 @@
"alert.unexpected.title": "Ups!",
"announcement.announcement": "Najava",
"attachments_list.unprocessed": "(neobrađeno)",
+ "audio.hide": "Sakrij audio",
"autosuggest_hashtag.per_week": "{count} tjedno",
"boost_modal.combo": "Možete pritisnuti {combo} kako biste preskočili ovo sljedeći put",
"bundle_column_error.error.title": "Oh, ne!",
@@ -66,6 +74,7 @@
"column.community": "Lokalna vremenska crta",
"column.directory": "Pregledavanje profila",
"column.domain_blocks": "Blokirane domene",
+ "column.favourites": "Favoriti",
"column.follow_requests": "Zahtjevi za praćenje",
"column.home": "Početna",
"column.lists": "Liste",
@@ -86,6 +95,8 @@
"community.column_settings.remote_only": "Samo udaljeno",
"compose.language.change": "Promijeni jezik",
"compose.language.search": "Pretraži jezike...",
+ "compose.published.open": "Otvori",
+ "compose.saved.body": "Post spremljen.",
"compose_form.direct_message_warning_learn_more": "Saznajte više",
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
@@ -179,6 +190,8 @@
"errors.unexpected_crash.copy_stacktrace": "Kopiraj stacktrace u međuspremnik",
"errors.unexpected_crash.report_issue": "Prijavi problem",
"explore.search_results": "Rezultati pretrage",
+ "explore.suggested_follows": "Ljudi",
+ "explore.title": "Pretraži",
"explore.trending_links": "Novosti",
"explore.trending_statuses": "Objave",
"explore.trending_tags": "Hashtagovi",
@@ -189,12 +202,17 @@
"filter_modal.select_filter.subtitle": "Odaberite postojeću kategoriju ili stvorite novu",
"filter_modal.select_filter.title": "Filtriraj ovu objavu",
"filter_modal.title.status": "Filtriraj objavu",
+ "firehose.all": "Sve",
+ "firehose.local": "Ovaj server",
"follow_request.authorize": "Autoriziraj",
"follow_request.reject": "Odbij",
+ "footer.about": "O aplikaciji",
"footer.get_app": "Preuzmi aplikaciju",
+ "footer.invite": "Pozovi ljude",
"footer.keyboard_shortcuts": "Tipkovni prečaci",
"footer.privacy_policy": "Pravila o zaštiti privatnosti",
"footer.source_code": "Prikaz izvornog koda",
+ "footer.status": "Stanje",
"generic.saved": "Spremljeno",
"getting_started.heading": "Počnimo",
"hashtag.column_header.tag_mode.all": "i {additional}",
@@ -212,7 +230,11 @@
"home.column_settings.show_reblogs": "Pokaži boostove",
"home.column_settings.show_replies": "Pokaži odgovore",
"home.hide_announcements": "Sakrij najave",
+ "home.pending_critical_update.title": "Dostupno je kritično sigurnosno ažuriranje!",
"home.show_announcements": "Prikaži najave",
+ "interaction_modal.login.action": "Odvedi me kući",
+ "interaction_modal.no_account_yet": "Nisi na Mastodonu?",
+ "interaction_modal.on_this_server": "Na ovom serveru",
"intervals.full.days": "{number, plural, one {# dan} other {# dana}}",
"intervals.full.hours": "{number, plural, one {# sat} few {# sata} other {# sati}}",
"intervals.full.minutes": "{number, plural, one {# minuta} few {# minute} other {# minuta}}",
diff --git a/app/javascript/mastodon/locales/intl_provider.tsx b/app/javascript/mastodon/locales/intl_provider.tsx
index 4fa8b2247c..68d4fcbd96 100644
--- a/app/javascript/mastodon/locales/intl_provider.tsx
+++ b/app/javascript/mastodon/locales/intl_provider.tsx
@@ -2,12 +2,14 @@ import { useEffect, useState } from 'react';
import { IntlProvider as BaseIntlProvider } from 'react-intl';
+import { isProduction } from 'mastodon/utils/environment';
+
import { getLocale, isLocaleLoaded } from './global_locale';
import { loadLocale } from './load_locale';
function onProviderError(error: unknown) {
// Silent the error, like upstream does
- if (process.env.NODE_ENV === 'production') return;
+ if (isProduction()) return;
// This browser does not advertise Intl support for this locale, we only print a warning
// As-per the spec, the browser should select the best matching locale
diff --git a/app/javascript/mastodon/locales/ms.json b/app/javascript/mastodon/locales/ms.json
index 3814e69151..a3bbd0067d 100644
--- a/app/javascript/mastodon/locales/ms.json
+++ b/app/javascript/mastodon/locales/ms.json
@@ -137,7 +137,7 @@
"compose.language.search": "Cari bahasa...",
"compose.published.body": "Pos telah diterbitkan.",
"compose.published.open": "Buka",
- "compose.saved.body": "Pos disimpan.",
+ "compose.saved.body": "Kiriman disimpan.",
"compose_form.direct_message_warning_learn_more": "Ketahui lebih lanjut",
"compose_form.encryption_warning": "Hantaran pada Mastodon tidak disulitkan hujung ke hujung. Jangan berkongsi sebarang maklumat sensitif melalui Mastodon.",
"compose_form.hashtag_warning": "Hantaran ini tidak akan disenaraikan di bawah mana-mana tanda pagar kerana ia tidak tersenarai. Hanya hantaran awam sahaja boleh dicari menggunakan tanda pagar.",
@@ -307,6 +307,9 @@
"home.explore_prompt.body": "Suapan rumah anda akan mempunyai gabungan pos daripada hashtag yang telah anda pilih untuk diikuti, orang yang telah anda pilih untuk diikuti dan pos yang mereka tingkatkan. Jika itu terasa terlalu senyap, anda mungkin mahu:",
"home.explore_prompt.title": "Ini adalah pusat operasi anda dalam Mastodon.",
"home.hide_announcements": "Sembunyikan pengumuman",
+ "home.pending_critical_update.body": "Sila kemas kini pelayan Mastodon anda secepat yang mungkin!",
+ "home.pending_critical_update.link": "Lihat pengemaskinian",
+ "home.pending_critical_update.title": "Kemas kini keselamatan kritikal tersedia!",
"home.show_announcements": "Tunjukkan pengumuman",
"interaction_modal.description.favourite": "Dengan akaun di Mastodon, anda boleh menggemari pos ini untuk memberitahu pengarang anda menghargainya dan menyimpannya untuk kemudian.",
"interaction_modal.description.follow": "Dengan akaun pada Mastodon, anda boleh mengikut {name} untuk menerima hantaran mereka di suapan rumah anda.",
@@ -408,6 +411,7 @@
"navigation_bar.lists": "Senarai",
"navigation_bar.logout": "Log keluar",
"navigation_bar.mutes": "Pengguna yang dibisukan",
+ "navigation_bar.opened_in_classic_interface": "Kiriman, akaun dan halaman tertentu yang lain dibuka secara lalai di antara muka web klasik.",
"navigation_bar.personal": "Peribadi",
"navigation_bar.pins": "Hantaran disemat",
"navigation_bar.preferences": "Keutamaan",
@@ -583,6 +587,7 @@
"search.quick_action.open_url": "Buka URL dalam Mastadon",
"search.quick_action.status_search": "Pos sepadan {x}",
"search.search_or_paste": "Cari atau tampal URL",
+ "search_popout.full_text_search_disabled_message": "Tidak tersedia di {domain}.",
"search_popout.language_code": "Kod bahasa ISO",
"search_popout.options": "Pilihan carian",
"search_popout.quick_actions": "Tindakan pantas",
diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json
index 3841237f47..63507be791 100644
--- a/app/javascript/mastodon/locales/sl.json
+++ b/app/javascript/mastodon/locales/sl.json
@@ -61,12 +61,12 @@
"account.requested_follow": "{name} vam želi slediti",
"account.share": "Deli profil osebe @{name}",
"account.show_reblogs": "Pokaži izpostavitve osebe @{name}",
- "account.statuses_counter": "{count, plural, one {{count} tut} two {{count} tuta} few {{count} tuti} other {{count} tutov}}",
+ "account.statuses_counter": "{count, plural, one {{count} objava} two {{count} objavi} few {{count} objave} other {{count} objav}}",
"account.unblock": "Odblokiraj @{name}",
"account.unblock_domain": "Odblokiraj domeno {domain}",
"account.unblock_short": "Odblokiraj",
"account.unendorse": "Ne vključi v profil",
- "account.unfollow": "Prenehaj slediti",
+ "account.unfollow": "Ne sledi več",
"account.unmute": "Odtišaj @{name}",
"account.unmute_notifications_short": "Izklopi utišanje obvestil",
"account.unmute_short": "Odtišaj",
@@ -185,7 +185,7 @@
"confirmations.redraft.message": "Ali ste prepričani, da želite izbrisati ta status in ga preoblikovati? Vzljubi in izpostavitve bodo izgubljeni, odgovori na izvirno objavo pa bodo osiroteli.",
"confirmations.reply.confirm": "Odgovori",
"confirmations.reply.message": "Odgovarjanje bo prepisalo sporočilo, ki ga trenutno sestavljate. Ali ste prepričani, da želite nadaljevati?",
- "confirmations.unfollow.confirm": "Prenehaj slediti",
+ "confirmations.unfollow.confirm": "Ne sledi več",
"confirmations.unfollow.message": "Ali ste prepričani, da ne želite več slediti {name}?",
"conversation.delete": "Izbriši pogovor",
"conversation.mark_as_read": "Označi kot prebrano",
@@ -301,7 +301,7 @@
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} objava} two {{counter} objavi} few {{counter} objav} other {{counter} objav}}",
"hashtag.follow": "Sledi ključniku",
"hashtag.unfollow": "Nehaj slediti ključniku",
- "hashtags.and_other": "…and {count, plural, one {} two {# več} few {# več}other {# več}}",
+ "hashtags.and_other": "…in še {count, plural, other {#}}",
"home.actions.go_to_explore": "Poglejte, kaj je v trendu",
"home.actions.go_to_suggestions": "Poiščite osebe, ki jim želite slediti",
"home.column_settings.basic": "Osnovno",
diff --git a/app/javascript/mastodon/main.jsx b/app/javascript/mastodon/main.jsx
index cd73cb572e..e7979d56a1 100644
--- a/app/javascript/mastodon/main.jsx
+++ b/app/javascript/mastodon/main.jsx
@@ -7,6 +7,8 @@ import * as perf from 'mastodon/performance';
import ready from 'mastodon/ready';
import { store } from 'mastodon/store';
+import { isProduction } from './utils/environment';
+
/**
* @returns {Promise}
*/
@@ -21,7 +23,7 @@ function main() {
root.render();
store.dispatch(setupBrowserNotifications());
- if (process.env.NODE_ENV === 'production' && me && 'serviceWorker' in navigator) {
+ if (isProduction() && me && 'serviceWorker' in navigator) {
const { Workbox } = await import('workbox-window');
const wb = new Workbox('/sw.js');
/** @type {ServiceWorkerRegistration} */
diff --git a/app/javascript/mastodon/models/account.ts b/app/javascript/mastodon/models/account.ts
new file mode 100644
index 0000000000..f20d2a2d3e
--- /dev/null
+++ b/app/javascript/mastodon/models/account.ts
@@ -0,0 +1,149 @@
+import type { RecordOf } from 'immutable';
+import { List, Record as ImmutableRecord } from 'immutable';
+
+import escapeTextContentForBrowser from 'escape-html';
+
+import type {
+ ApiAccountFieldJSON,
+ ApiAccountRoleJSON,
+ ApiAccountJSON,
+} from 'mastodon/api_types/accounts';
+import type { ApiCustomEmojiJSON } from 'mastodon/api_types/custom_emoji';
+import emojify from 'mastodon/features/emoji/emoji';
+import { unescapeHTML } from 'mastodon/utils/html';
+
+import { CustomEmojiFactory } from './custom_emoji';
+import type { CustomEmoji } from './custom_emoji';
+
+// AccountField
+interface AccountFieldShape extends Required {
+ name_emojified: string;
+ value_emojified: string;
+ value_plain: string | null;
+}
+
+type AccountField = RecordOf;
+
+const AccountFieldFactory = ImmutableRecord({
+ name: '',
+ value: '',
+ verified_at: null,
+ name_emojified: '',
+ value_emojified: '',
+ value_plain: null,
+});
+
+// AccountRole
+export type AccountRoleShape = ApiAccountRoleJSON;
+export type AccountRole = RecordOf;
+
+const AccountRoleFactory = ImmutableRecord({
+ color: '',
+ id: '',
+ name: '',
+});
+
+// Account
+export interface AccountShape
+ extends Required<
+ Omit
+ > {
+ emojis: List;
+ fields: List;
+ roles: List;
+ display_name_html: string;
+ note_emojified: string;
+ note_plain: string | null;
+ hidden: boolean;
+ moved: string | null;
+}
+
+export type Account = RecordOf;
+
+export const accountDefaultValues: AccountShape = {
+ acct: '',
+ avatar: '',
+ avatar_static: '',
+ bot: false,
+ created_at: '',
+ discoverable: false,
+ display_name: '',
+ display_name_html: '',
+ emojis: List(),
+ fields: List(),
+ group: false,
+ header: '',
+ header_static: '',
+ id: '',
+ last_status_at: '',
+ locked: false,
+ noindex: false,
+ note: '',
+ note_emojified: '',
+ note_plain: 'string',
+ roles: List(),
+ uri: '',
+ url: '',
+ username: '',
+ followers_count: 0,
+ following_count: 0,
+ statuses_count: 0,
+ hidden: false,
+ suspended: false,
+ memorial: false,
+ limited: false,
+ moved: null,
+};
+
+const AccountFactory = ImmutableRecord(accountDefaultValues);
+
+type EmojiMap = Record;
+
+function makeEmojiMap(emojis: ApiCustomEmojiJSON[]) {
+ return emojis.reduce((obj, emoji) => {
+ obj[`:${emoji.shortcode}:`] = emoji;
+ return obj;
+ }, {});
+}
+
+function createAccountField(
+ jsonField: ApiAccountFieldJSON,
+ emojiMap: EmojiMap,
+) {
+ return AccountFieldFactory({
+ ...jsonField,
+ name_emojified: emojify(
+ escapeTextContentForBrowser(jsonField.name),
+ emojiMap,
+ ),
+ value_emojified: emojify(jsonField.value, emojiMap),
+ value_plain: unescapeHTML(jsonField.value),
+ });
+}
+
+export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) {
+ const { moved, ...accountJSON } = serverJSON;
+
+ const emojiMap = makeEmojiMap(accountJSON.emojis);
+
+ const displayName =
+ accountJSON.display_name.trim().length === 0
+ ? accountJSON.username
+ : accountJSON.display_name;
+
+ return AccountFactory({
+ ...accountJSON,
+ moved: moved?.id,
+ fields: List(
+ serverJSON.fields.map((field) => createAccountField(field, emojiMap)),
+ ),
+ emojis: List(serverJSON.emojis.map((emoji) => CustomEmojiFactory(emoji))),
+ roles: List(serverJSON.roles?.map((role) => AccountRoleFactory(role))),
+ display_name_html: emojify(
+ escapeTextContentForBrowser(displayName),
+ emojiMap,
+ ),
+ note_emojified: emojify(accountJSON.note, emojiMap),
+ note_plain: unescapeHTML(accountJSON.note),
+ });
+}
diff --git a/app/javascript/mastodon/models/custom_emoji.ts b/app/javascript/mastodon/models/custom_emoji.ts
new file mode 100644
index 0000000000..76479f3aeb
--- /dev/null
+++ b/app/javascript/mastodon/models/custom_emoji.ts
@@ -0,0 +1,15 @@
+import type { RecordOf } from 'immutable';
+import { Record } from 'immutable';
+
+import type { ApiCustomEmojiJSON } from 'mastodon/api_types/custom_emoji';
+
+type CustomEmojiShape = Required; // no changes from server shape
+export type CustomEmoji = RecordOf;
+
+export const CustomEmojiFactory = Record({
+ shortcode: '',
+ static_url: '',
+ url: '',
+ category: '',
+ visible_in_picker: false,
+});
diff --git a/app/javascript/mastodon/models/relationship.ts b/app/javascript/mastodon/models/relationship.ts
new file mode 100644
index 0000000000..115b278738
--- /dev/null
+++ b/app/javascript/mastodon/models/relationship.ts
@@ -0,0 +1,29 @@
+import type { RecordOf } from 'immutable';
+import { Record } from 'immutable';
+
+import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
+
+type RelationshipShape = Required; // no changes from server shape
+export type Relationship = RecordOf;
+
+const RelationshipFactory = Record({
+ blocked_by: false,
+ blocking: false,
+ domain_blocking: false,
+ endorsed: false,
+ followed_by: false,
+ following: false,
+ id: '',
+ languages: null,
+ muting_notifications: false,
+ muting: false,
+ note: '',
+ notifying: false,
+ requested_by: false,
+ requested: false,
+ showing_reblogs: false,
+});
+
+export function createRelationship(attributes: Partial) {
+ return RelationshipFactory(attributes);
+}
diff --git a/app/javascript/mastodon/performance.js b/app/javascript/mastodon/performance.js
index 42849c82b1..3bca95e85e 100644
--- a/app/javascript/mastodon/performance.js
+++ b/app/javascript/mastodon/performance.js
@@ -5,7 +5,9 @@
import * as marky from 'marky';
-if (process.env.NODE_ENV === 'development') {
+import { isDevelopment } from './utils/environment';
+
+if (isDevelopment()) {
if (typeof performance !== 'undefined' && performance.setResourceTimingBufferSize) {
// Increase Firefox's performance entry limit; otherwise it's capped to 150.
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1331135
@@ -18,13 +20,13 @@ if (process.env.NODE_ENV === 'development') {
}
export function start(name) {
- if (process.env.NODE_ENV === 'development') {
+ if (isDevelopment()) {
marky.mark(name);
}
}
export function stop(name) {
- if (process.env.NODE_ENV === 'development') {
+ if (isDevelopment()) {
marky.stop(name);
}
}
diff --git a/app/javascript/mastodon/polyfills/base_polyfills.ts b/app/javascript/mastodon/polyfills/base_polyfills.ts
deleted file mode 100644
index 71565236cd..0000000000
--- a/app/javascript/mastodon/polyfills/base_polyfills.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import 'core-js/features/object/assign';
-import 'core-js/features/object/values';
-import 'core-js/features/symbol';
-import 'core-js/features/promise/finally';
-import { decode as decodeBase64 } from '../utils/base64';
-
-if (!Object.hasOwn(HTMLCanvasElement.prototype, 'toBlob')) {
- const BASE64_MARKER = ';base64,';
-
- Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
- value: function (
- this: HTMLCanvasElement,
- callback: BlobCallback,
- type = 'image/png',
- quality: unknown,
- ) {
- const dataURL: string = this.toDataURL(type, quality);
- let data;
-
- if (dataURL.includes(BASE64_MARKER)) {
- const [, base64] = dataURL.split(BASE64_MARKER);
- data = decodeBase64(base64);
- } else {
- [, data] = dataURL.split(',');
- }
-
- callback(new Blob([data], { type }));
- },
- });
-}
diff --git a/app/javascript/mastodon/polyfills/extra_polyfills.ts b/app/javascript/mastodon/polyfills/extra_polyfills.ts
index e6c69de8b5..a8d5530c5f 100644
--- a/app/javascript/mastodon/polyfills/extra_polyfills.ts
+++ b/app/javascript/mastodon/polyfills/extra_polyfills.ts
@@ -1,2 +1 @@
-import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only';
import 'requestidlecallback';
diff --git a/app/javascript/mastodon/polyfills/index.ts b/app/javascript/mastodon/polyfills/index.ts
index e166c09d0e..431c5b0f30 100644
--- a/app/javascript/mastodon/polyfills/index.ts
+++ b/app/javascript/mastodon/polyfills/index.ts
@@ -4,39 +4,18 @@
import { loadIntlPolyfills } from './intl';
-function importBasePolyfills() {
- return import(/* webpackChunkName: "base_polyfills" */ './base_polyfills');
-}
-
function importExtraPolyfills() {
return import(/* webpackChunkName: "extra_polyfills" */ './extra_polyfills');
}
export function loadPolyfills() {
- const needsBasePolyfills = !(
- 'toBlob' in HTMLCanvasElement.prototype &&
- 'assign' in Object &&
- 'values' in Object &&
- 'Symbol' in window &&
- 'finally' in Promise.prototype
- );
-
- // Latest version of Firefox and Safari do not have IntersectionObserver.
- // Edge does not have requestIdleCallback.
+ // Safari does not have requestIdleCallback.
// This avoids shipping them all the polyfills.
- /* eslint-disable @typescript-eslint/no-unnecessary-condition -- those properties might not exist in old browsers, even if they are always here in types */
- const needsExtraPolyfills = !(
- window.AbortController &&
- window.IntersectionObserver &&
- window.IntersectionObserverEntry &&
- 'isIntersecting' in IntersectionObserverEntry.prototype &&
- window.requestIdleCallback
- );
- /* eslint-enable @typescript-eslint/no-unnecessary-condition */
+ const needsExtraPolyfills = !window.requestIdleCallback;
return Promise.all([
loadIntlPolyfills(),
- needsBasePolyfills && importBasePolyfills(),
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- those properties might not exist in old browsers, even if they are always here in types
needsExtraPolyfills && importExtraPolyfills(),
]);
}
diff --git a/app/javascript/mastodon/reducers/accounts.js b/app/javascript/mastodon/reducers/accounts.js
deleted file mode 100644
index 76122cc63b..0000000000
--- a/app/javascript/mastodon/reducers/accounts.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { Map as ImmutableMap, fromJS } from 'immutable';
-
-import { ACCOUNT_REVEAL } from 'mastodon/actions/accounts';
-import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from 'mastodon/actions/importer';
-
-const initialState = ImmutableMap();
-
-const normalizeAccount = (state, account) => {
- account = { ...account };
-
- delete account.followers_count;
- delete account.following_count;
- delete account.statuses_count;
-
- account.hidden = state.getIn([account.id, 'hidden']) === false ? false : account.limited;
-
- return state.set(account.id, fromJS(account));
-};
-
-const normalizeAccounts = (state, accounts) => {
- accounts.forEach(account => {
- state = normalizeAccount(state, account);
- });
-
- return state;
-};
-
-export default function accounts(state = initialState, action) {
- switch(action.type) {
- case ACCOUNT_IMPORT:
- return normalizeAccount(state, action.account);
- case ACCOUNTS_IMPORT:
- return normalizeAccounts(state, action.accounts);
- case ACCOUNT_REVEAL:
- return state.setIn([action.id, 'hidden'], false);
- default:
- return state;
- }
-}
diff --git a/app/javascript/mastodon/reducers/accounts.ts b/app/javascript/mastodon/reducers/accounts.ts
new file mode 100644
index 0000000000..f7270eb60a
--- /dev/null
+++ b/app/javascript/mastodon/reducers/accounts.ts
@@ -0,0 +1,84 @@
+import { Map as ImmutableMap } from 'immutable';
+
+import type { Reducer } from 'redux';
+
+import {
+ followAccountSuccess,
+ unfollowAccountSuccess,
+ importAccounts,
+ revealAccount,
+} from 'mastodon/actions/accounts_typed';
+import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
+import { me } from 'mastodon/initial_state';
+import type { Account } from 'mastodon/models/account';
+import { createAccountFromServerJSON } from 'mastodon/models/account';
+
+const initialState = ImmutableMap();
+
+const normalizeAccount = (
+ state: typeof initialState,
+ account: ApiAccountJSON,
+) => {
+ return state.set(
+ account.id,
+ createAccountFromServerJSON(account).set(
+ 'hidden',
+ state.get(account.id)?.hidden === false
+ ? false
+ : account.limited || false,
+ ),
+ );
+};
+
+const normalizeAccounts = (
+ state: typeof initialState,
+ accounts: ApiAccountJSON[],
+) => {
+ accounts.forEach((account) => {
+ state = normalizeAccount(state, account);
+ });
+
+ return state;
+};
+
+function getCurrentUser() {
+ if (!me)
+ throw new Error(
+ 'No current user (me) defined when calling `accountsReducer`',
+ );
+
+ return me;
+}
+
+export const accountsReducer: Reducer = (
+ state = initialState,
+ action,
+) => {
+ if (revealAccount.match(action))
+ return state.setIn([action.payload.id, 'hidden'], false);
+ else if (importAccounts.match(action))
+ return normalizeAccounts(state, action.payload.accounts);
+ else if (followAccountSuccess.match(action)) {
+ return state
+ .update(
+ action.payload.relationship.id,
+ (account) => account?.update('followers_count', (n) => n + 1),
+ )
+ .update(
+ getCurrentUser(),
+ (account) => account?.update('following_count', (n) => n + 1),
+ );
+ } else if (unfollowAccountSuccess.match(action))
+ return state
+ .update(
+ action.payload.relationship.id,
+ (account) =>
+ account?.update('followers_count', (n) => Math.max(0, n - 1)),
+ )
+ .update(
+ getCurrentUser(),
+ (account) =>
+ account?.update('following_count', (n) => Math.max(0, n - 1)),
+ );
+ else return state;
+};
diff --git a/app/javascript/mastodon/reducers/accounts_counters.js b/app/javascript/mastodon/reducers/accounts_counters.js
deleted file mode 100644
index eb7878deb9..0000000000
--- a/app/javascript/mastodon/reducers/accounts_counters.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Map as ImmutableMap, fromJS } from 'immutable';
-
-import { me } from 'mastodon/initial_state';
-
-import {
- ACCOUNT_FOLLOW_SUCCESS,
- ACCOUNT_UNFOLLOW_SUCCESS,
-} from '../actions/accounts';
-import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer';
-
-const normalizeAccount = (state, account) => state.set(account.id, fromJS({
- followers_count: account.followers_count,
- following_count: account.following_count,
- statuses_count: account.statuses_count,
-}));
-
-const normalizeAccounts = (state, accounts) => {
- accounts.forEach(account => {
- state = normalizeAccount(state, account);
- });
-
- return state;
-};
-
-const incrementFollowers = (state, accountId) =>
- state.updateIn([accountId, 'followers_count'], num => num + 1)
- .updateIn([me, 'following_count'], num => num + 1);
-
-const decrementFollowers = (state, accountId) =>
- state.updateIn([accountId, 'followers_count'], num => Math.max(0, num - 1))
- .updateIn([me, 'following_count'], num => Math.max(0, num - 1));
-
-const initialState = ImmutableMap();
-
-export default function accountsCounters(state = initialState, action) {
- switch(action.type) {
- case ACCOUNT_IMPORT:
- return normalizeAccount(state, action.account);
- case ACCOUNTS_IMPORT:
- return normalizeAccounts(state, action.accounts);
- case ACCOUNT_FOLLOW_SUCCESS:
- return action.alreadyFollowing ? state :
- incrementFollowers(state, action.relationship.id);
- case ACCOUNT_UNFOLLOW_SUCCESS:
- return decrementFollowers(state, action.relationship.id);
- default:
- return state;
- }
-}
diff --git a/app/javascript/mastodon/reducers/accounts_map.js b/app/javascript/mastodon/reducers/accounts_map.js
index fca0e3ce1e..d5ecad7dbf 100644
--- a/app/javascript/mastodon/reducers/accounts_map.js
+++ b/app/javascript/mastodon/reducers/accounts_map.js
@@ -1,7 +1,7 @@
import { Map as ImmutableMap } from 'immutable';
import { ACCOUNT_LOOKUP_FAIL } from '../actions/accounts';
-import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from '../actions/importer';
+import { importAccounts } from '../actions/accounts_typed';
export const normalizeForLookup = str => str.toLowerCase();
@@ -11,10 +11,8 @@ export default function accountsMap(state = initialState, action) {
switch(action.type) {
case ACCOUNT_LOOKUP_FAIL:
return action.error?.response?.status === 404 ? state.set(normalizeForLookup(action.acct), null) : state;
- case ACCOUNT_IMPORT:
- return state.set(normalizeForLookup(action.account.acct), action.account.id);
- case ACCOUNTS_IMPORT:
- return state.withMutations(map => action.accounts.forEach(account => map.set(normalizeForLookup(account.acct), account.id)));
+ case importAccounts.type:
+ return state.withMutations(map => action.payload.accounts.forEach(account => map.set(normalizeForLookup(account.acct), account.id)));
default:
return state;
}
diff --git a/app/javascript/mastodon/reducers/contexts.js b/app/javascript/mastodon/reducers/contexts.js
index 32e194dd42..f7d7419a4e 100644
--- a/app/javascript/mastodon/reducers/contexts.js
+++ b/app/javascript/mastodon/reducers/contexts.js
@@ -1,8 +1,8 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import {
- ACCOUNT_BLOCK_SUCCESS,
- ACCOUNT_MUTE_SUCCESS,
+ blockAccountSuccess,
+ muteAccountSuccess,
} from '../actions/accounts';
import { CONTEXT_FETCH_SUCCESS } from '../actions/statuses';
import { TIMELINE_DELETE, TIMELINE_UPDATE } from '../actions/timelines';
@@ -92,9 +92,9 @@ const updateContext = (state, status) => {
export default function replies(state = initialState, action) {
switch(action.type) {
- case ACCOUNT_BLOCK_SUCCESS:
- case ACCOUNT_MUTE_SUCCESS:
- return filterContexts(state, action.relationship, action.statuses);
+ case blockAccountSuccess.type:
+ case muteAccountSuccess.type:
+ return filterContexts(state, action.payload.relationship, action.payload.statuses);
case CONTEXT_FETCH_SUCCESS:
return normalizeContext(state, action.id, action.ancestors, action.descendants);
case TIMELINE_DELETE:
diff --git a/app/javascript/mastodon/reducers/conversations.js b/app/javascript/mastodon/reducers/conversations.js
index 247e8a5977..3e99e680e3 100644
--- a/app/javascript/mastodon/reducers/conversations.js
+++ b/app/javascript/mastodon/reducers/conversations.js
@@ -1,7 +1,7 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'mastodon/actions/accounts';
-import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
+import { blockAccountSuccess, muteAccountSuccess } from 'mastodon/actions/accounts';
+import { blockDomainSuccess } from 'mastodon/actions/domain_blocks';
import {
CONVERSATIONS_MOUNT,
@@ -105,11 +105,11 @@ export default function conversations(state = initialState, action) {
return item;
}));
- case ACCOUNT_BLOCK_SUCCESS:
- case ACCOUNT_MUTE_SUCCESS:
- return filterConversations(state, [action.relationship.id]);
- case DOMAIN_BLOCK_SUCCESS:
- return filterConversations(state, action.accounts);
+ case blockAccountSuccess.type:
+ case muteAccountSuccess.type:
+ return filterConversations(state, [action.payload.relationship.id]);
+ case blockDomainSuccess.type:
+ return filterConversations(state, action.payload.accounts);
case CONVERSATIONS_DELETE_SUCCESS:
return state.update('items', list => list.filterNot(item => item.get('id') === action.id));
default:
diff --git a/app/javascript/mastodon/reducers/domain_lists.js b/app/javascript/mastodon/reducers/domain_lists.js
index 8cdd3ba376..5f63c77f5d 100644
--- a/app/javascript/mastodon/reducers/domain_lists.js
+++ b/app/javascript/mastodon/reducers/domain_lists.js
@@ -3,7 +3,7 @@ import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutabl
import {
DOMAIN_BLOCKS_FETCH_SUCCESS,
DOMAIN_BLOCKS_EXPAND_SUCCESS,
- DOMAIN_UNBLOCK_SUCCESS,
+ unblockDomainSuccess
} from '../actions/domain_blocks';
const initialState = ImmutableMap({
@@ -18,8 +18,8 @@ export default function domainLists(state = initialState, action) {
return state.setIn(['blocks', 'items'], ImmutableOrderedSet(action.domains)).setIn(['blocks', 'next'], action.next);
case DOMAIN_BLOCKS_EXPAND_SUCCESS:
return state.updateIn(['blocks', 'items'], set => set.union(action.domains)).setIn(['blocks', 'next'], action.next);
- case DOMAIN_UNBLOCK_SUCCESS:
- return state.updateIn(['blocks', 'items'], set => set.delete(action.domain));
+ case unblockDomainSuccess.type:
+ return state.updateIn(['blocks', 'items'], set => set.delete(action.payload.domain));
default:
return state;
}
diff --git a/app/javascript/mastodon/reducers/index.ts b/app/javascript/mastodon/reducers/index.ts
index 722f04f370..ecef633873 100644
--- a/app/javascript/mastodon/reducers/index.ts
+++ b/app/javascript/mastodon/reducers/index.ts
@@ -3,8 +3,7 @@ import { Record as ImmutableRecord } from 'immutable';
import { loadingBarReducer } from 'react-redux-loading-bar';
import { combineReducers } from 'redux-immutable';
-import accounts from './accounts';
-import accounts_counters from './accounts_counters';
+import { accountsReducer } from './accounts';
import accounts_map from './accounts_map';
import alerts from './alerts';
import announcements from './announcements';
@@ -32,7 +31,7 @@ import notifications from './notifications';
import picture_in_picture from './picture_in_picture';
import polls from './polls';
import push_notifications from './push_notifications';
-import relationships from './relationships';
+import { relationshipsReducer } from './relationships';
import search from './search';
import server from './server';
import settings from './settings';
@@ -55,11 +54,10 @@ const reducers = {
user_lists,
domain_lists,
status_lists,
- accounts,
- accounts_counters,
+ accounts: accountsReducer,
accounts_map,
statuses,
- relationships,
+ relationships: relationshipsReducer,
settings,
push_notifications,
mutes,
diff --git a/app/javascript/mastodon/reducers/notifications.js b/app/javascript/mastodon/reducers/notifications.js
index 66870bec55..4a7a822a35 100644
--- a/app/javascript/mastodon/reducers/notifications.js
+++ b/app/javascript/mastodon/reducers/notifications.js
@@ -1,12 +1,12 @@
import { fromJS, Map as ImmutableMap, List as ImmutableList } from 'immutable';
-import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
+import { blockDomainSuccess } from 'mastodon/actions/domain_blocks';
import {
- ACCOUNT_BLOCK_SUCCESS,
- ACCOUNT_MUTE_SUCCESS,
- FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
- FOLLOW_REQUEST_REJECT_SUCCESS,
+ authorizeFollowRequestSuccess,
+ blockAccountSuccess,
+ muteAccountSuccess,
+ rejectFollowRequestSuccess,
} from '../actions/accounts';
import {
focusApp,
@@ -16,7 +16,7 @@ import {
MARKERS_FETCH_SUCCESS,
} from '../actions/markers';
import {
- NOTIFICATIONS_UPDATE,
+ notificationsUpdate,
NOTIFICATIONS_EXPAND_SUCCESS,
NOTIFICATIONS_EXPAND_REQUEST,
NOTIFICATIONS_EXPAND_FAIL,
@@ -274,19 +274,19 @@ export default function notifications(state = initialState, action) {
return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', true);
case NOTIFICATIONS_SCROLL_TOP:
return updateTop(state, action.top);
- case NOTIFICATIONS_UPDATE:
- return normalizeNotification(state, action.notification, action.usePendingItems);
+ case notificationsUpdate.type:
+ return normalizeNotification(state, action.payload.notification, action.payload.usePendingItems);
case NOTIFICATIONS_EXPAND_SUCCESS:
return expandNormalizedNotifications(state, action.notifications, action.next, action.isLoadingMore, action.isLoadingRecent, action.usePendingItems);
- case ACCOUNT_BLOCK_SUCCESS:
- return filterNotifications(state, [action.relationship.id]);
- case ACCOUNT_MUTE_SUCCESS:
- return action.relationship.muting_notifications ? filterNotifications(state, [action.relationship.id]) : state;
- case DOMAIN_BLOCK_SUCCESS:
- return filterNotifications(state, action.accounts);
- case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
- case FOLLOW_REQUEST_REJECT_SUCCESS:
- return filterNotifications(state, [action.id], 'follow_request');
+ case blockAccountSuccess.type:
+ return filterNotifications(state, [action.payload.relationship.id]);
+ case muteAccountSuccess.type:
+ return action.relationship.muting_notifications ? filterNotifications(state, [action.payload.relationship.id]) : state;
+ case blockDomainSuccess.type:
+ return filterNotifications(state, action.payload.accounts);
+ case authorizeFollowRequestSuccess.type:
+ case rejectFollowRequestSuccess.type:
+ return filterNotifications(state, [action.payload.id], 'follow_request');
case NOTIFICATIONS_CLEAR:
return state.set('items', ImmutableList()).set('pendingItems', ImmutableList()).set('hasMore', false);
case TIMELINE_DELETE:
diff --git a/app/javascript/mastodon/reducers/relationships.js b/app/javascript/mastodon/reducers/relationships.js
deleted file mode 100644
index 32b4b4f371..0000000000
--- a/app/javascript/mastodon/reducers/relationships.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { Map as ImmutableMap, fromJS } from 'immutable';
-
-import {
- submitAccountNote,
-} from '../actions/account_notes';
-import {
- ACCOUNT_FOLLOW_SUCCESS,
- ACCOUNT_FOLLOW_REQUEST,
- ACCOUNT_FOLLOW_FAIL,
- ACCOUNT_UNFOLLOW_SUCCESS,
- ACCOUNT_UNFOLLOW_REQUEST,
- ACCOUNT_UNFOLLOW_FAIL,
- ACCOUNT_BLOCK_SUCCESS,
- ACCOUNT_UNBLOCK_SUCCESS,
- ACCOUNT_MUTE_SUCCESS,
- ACCOUNT_UNMUTE_SUCCESS,
- ACCOUNT_PIN_SUCCESS,
- ACCOUNT_UNPIN_SUCCESS,
- RELATIONSHIPS_FETCH_SUCCESS,
- FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
- FOLLOW_REQUEST_REJECT_SUCCESS,
-} from '../actions/accounts';
-import {
- DOMAIN_BLOCK_SUCCESS,
- DOMAIN_UNBLOCK_SUCCESS,
-} from '../actions/domain_blocks';
-import {
- NOTIFICATIONS_UPDATE,
-} from '../actions/notifications';
-
-
-const normalizeRelationship = (state, relationship) => state.set(relationship.id, fromJS(relationship));
-
-const normalizeRelationships = (state, relationships) => {
- relationships.forEach(relationship => {
- state = normalizeRelationship(state, relationship);
- });
-
- return state;
-};
-
-const setDomainBlocking = (state, accounts, blocking) => {
- return state.withMutations(map => {
- accounts.forEach(id => {
- map.setIn([id, 'domain_blocking'], blocking);
- });
- });
-};
-
-const initialState = ImmutableMap();
-
-export default function relationships(state = initialState, action) {
- switch(action.type) {
- case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
- return state.setIn([action.id, 'followed_by'], true).setIn([action.id, 'requested_by'], false);
- case FOLLOW_REQUEST_REJECT_SUCCESS:
- return state.setIn([action.id, 'followed_by'], false).setIn([action.id, 'requested_by'], false);
- case NOTIFICATIONS_UPDATE:
- return action.notification.type === 'follow_request' ? state.setIn([action.notification.account.id, 'requested_by'], true) : state;
- case ACCOUNT_FOLLOW_REQUEST:
- return state.getIn([action.id, 'following']) ? state : state.setIn([action.id, action.locked ? 'requested' : 'following'], true);
- case ACCOUNT_FOLLOW_FAIL:
- return state.setIn([action.id, action.locked ? 'requested' : 'following'], false);
- case ACCOUNT_UNFOLLOW_REQUEST:
- return state.setIn([action.id, 'following'], false);
- case ACCOUNT_UNFOLLOW_FAIL:
- return state.setIn([action.id, 'following'], true);
- case ACCOUNT_FOLLOW_SUCCESS:
- case ACCOUNT_UNFOLLOW_SUCCESS:
- case ACCOUNT_BLOCK_SUCCESS:
- case ACCOUNT_UNBLOCK_SUCCESS:
- case ACCOUNT_MUTE_SUCCESS:
- case ACCOUNT_UNMUTE_SUCCESS:
- case ACCOUNT_PIN_SUCCESS:
- case ACCOUNT_UNPIN_SUCCESS:
- return normalizeRelationship(state, action.relationship);
- case RELATIONSHIPS_FETCH_SUCCESS:
- return normalizeRelationships(state, action.relationships);
- case submitAccountNote.fulfilled:
- return normalizeRelationship(state, action.payload.relationship);
- case DOMAIN_BLOCK_SUCCESS:
- return setDomainBlocking(state, action.accounts, true);
- case DOMAIN_UNBLOCK_SUCCESS:
- return setDomainBlocking(state, action.accounts, false);
- default:
- return state;
- }
-}
diff --git a/app/javascript/mastodon/reducers/relationships.ts b/app/javascript/mastodon/reducers/relationships.ts
new file mode 100644
index 0000000000..2ba61839c7
--- /dev/null
+++ b/app/javascript/mastodon/reducers/relationships.ts
@@ -0,0 +1,123 @@
+import { Map as ImmutableMap } from 'immutable';
+
+import { isFulfilled } from '@reduxjs/toolkit';
+import type { Reducer } from 'redux';
+
+import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
+import type { Account } from 'mastodon/models/account';
+import { createRelationship } from 'mastodon/models/relationship';
+import type { Relationship } from 'mastodon/models/relationship';
+
+import { submitAccountNote } from '../actions/account_notes';
+import {
+ followAccountSuccess,
+ unfollowAccountSuccess,
+ authorizeFollowRequestSuccess,
+ rejectFollowRequestSuccess,
+ followAccountRequest,
+ followAccountFail,
+ unfollowAccountRequest,
+ unfollowAccountFail,
+ blockAccountSuccess,
+ unblockAccountSuccess,
+ muteAccountSuccess,
+ unmuteAccountSuccess,
+ pinAccountSuccess,
+ unpinAccountSuccess,
+ fetchRelationshipsSuccess,
+} from '../actions/accounts_typed';
+import {
+ blockDomainSuccess,
+ unblockDomainSuccess,
+} from '../actions/domain_blocks_typed';
+import { notificationsUpdate } from '../actions/notifications_typed';
+
+const initialState = ImmutableMap();
+type State = typeof initialState;
+
+const normalizeRelationship = (
+ state: State,
+ relationship: ApiRelationshipJSON,
+) => state.set(relationship.id, createRelationship(relationship));
+
+const normalizeRelationships = (
+ state: State,
+ relationships: ApiRelationshipJSON[],
+) => {
+ relationships.forEach((relationship) => {
+ state = normalizeRelationship(state, relationship);
+ });
+
+ return state;
+};
+
+const setDomainBlocking = (
+ state: State,
+ accounts: Account[],
+ blocking: boolean,
+) => {
+ return state.withMutations((map) => {
+ accounts.forEach((id) => {
+ map.setIn([id, 'domain_blocking'], blocking);
+ });
+ });
+};
+
+export const relationshipsReducer: Reducer = (
+ state = initialState,
+ action,
+) => {
+ if (authorizeFollowRequestSuccess.match(action))
+ return state
+ .setIn([action.payload.id, 'followed_by'], true)
+ .setIn([action.payload.id, 'requested_by'], false);
+ else if (rejectFollowRequestSuccess.match(action))
+ return state
+ .setIn([action.payload.id, 'followed_by'], false)
+ .setIn([action.payload.id, 'requested_by'], false);
+ else if (notificationsUpdate.match(action))
+ return action.payload.notification.type === 'follow_request'
+ ? state.setIn(
+ [action.payload.notification.account.id, 'requested_by'],
+ true,
+ )
+ : state;
+ else if (followAccountRequest.match(action))
+ return state.getIn([action.payload.id, 'following'])
+ ? state
+ : state.setIn(
+ [
+ action.payload.id,
+ action.payload.locked ? 'requested' : 'following',
+ ],
+ true,
+ );
+ else if (followAccountFail.match(action))
+ return state.setIn(
+ [action.payload.id, action.payload.locked ? 'requested' : 'following'],
+ false,
+ );
+ else if (unfollowAccountRequest.match(action))
+ return state.setIn([action.payload.id, 'following'], false);
+ else if (unfollowAccountFail.match(action))
+ return state.setIn([action.payload.id, 'following'], true);
+ else if (
+ followAccountSuccess.match(action) ||
+ unfollowAccountSuccess.match(action) ||
+ blockAccountSuccess.match(action) ||
+ unblockAccountSuccess.match(action) ||
+ muteAccountSuccess.match(action) ||
+ unmuteAccountSuccess.match(action) ||
+ pinAccountSuccess.match(action) ||
+ unpinAccountSuccess.match(action) ||
+ isFulfilled(submitAccountNote)(action)
+ )
+ return normalizeRelationship(state, action.payload.relationship);
+ else if (fetchRelationshipsSuccess.match(action))
+ return normalizeRelationships(state, action.payload.relationships);
+ else if (blockDomainSuccess.match(action))
+ return setDomainBlocking(state, action.payload.accounts, true);
+ else if (unblockDomainSuccess.match(action))
+ return setDomainBlocking(state, action.payload.accounts, false);
+ else return state;
+};
diff --git a/app/javascript/mastodon/reducers/status_lists.js b/app/javascript/mastodon/reducers/status_lists.js
index 41cc07341c..6cb6a937bb 100644
--- a/app/javascript/mastodon/reducers/status_lists.js
+++ b/app/javascript/mastodon/reducers/status_lists.js
@@ -1,8 +1,8 @@
import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable';
import {
- ACCOUNT_BLOCK_SUCCESS,
- ACCOUNT_MUTE_SUCCESS,
+ blockAccountSuccess,
+ muteAccountSuccess,
} from '../actions/accounts';
import {
BOOKMARKED_STATUSES_FETCH_REQUEST,
@@ -142,9 +142,9 @@ export default function statusLists(state = initialState, action) {
return prependOneToList(state, 'pins', action.status);
case UNPIN_SUCCESS:
return removeOneFromList(state, 'pins', action.status);
- case ACCOUNT_BLOCK_SUCCESS:
- case ACCOUNT_MUTE_SUCCESS:
- return state.updateIn(['trending', 'items'], ImmutableOrderedSet(), list => list.filterNot(statusId => action.statuses.getIn([statusId, 'account']) === action.relationship.id));
+ case blockAccountSuccess.type:
+ case muteAccountSuccess.type:
+ return state.updateIn(['trending', 'items'], ImmutableOrderedSet(), list => list.filterNot(statusId => action.payload.statuses.getIn([statusId, 'account']) === action.payload.relationship.id));
default:
return state;
}
diff --git a/app/javascript/mastodon/reducers/suggestions.js b/app/javascript/mastodon/reducers/suggestions.js
index ce1bcc7740..0f224ff4b9 100644
--- a/app/javascript/mastodon/reducers/suggestions.js
+++ b/app/javascript/mastodon/reducers/suggestions.js
@@ -1,7 +1,7 @@
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
-import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'mastodon/actions/accounts';
-import { DOMAIN_BLOCK_SUCCESS } from 'mastodon/actions/domain_blocks';
+import { blockAccountSuccess, muteAccountSuccess } from 'mastodon/actions/accounts';
+import { blockDomainSuccess } from 'mastodon/actions/domain_blocks';
import {
SUGGESTIONS_FETCH_REQUEST,
@@ -29,11 +29,11 @@ export default function suggestionsReducer(state = initialState, action) {
return state.set('isLoading', false);
case SUGGESTIONS_DISMISS:
return state.update('items', list => list.filterNot(x => x.account === action.id));
- case ACCOUNT_BLOCK_SUCCESS:
- case ACCOUNT_MUTE_SUCCESS:
- return state.update('items', list => list.filterNot(x => x.account === action.relationship.id));
- case DOMAIN_BLOCK_SUCCESS:
- return state.update('items', list => list.filterNot(x => action.accounts.includes(x.account)));
+ case blockAccountSuccess.type:
+ case muteAccountSuccess.type:
+ return state.update('items', list => list.filterNot(x => x.account === action.payload.relationship.id));
+ case blockDomainSuccess.type:
+ return state.update('items', list => list.filterNot(x => action.payload.accounts.includes(x.account)));
default:
return state;
}
diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js
index cb3da50727..43dedd6e6d 100644
--- a/app/javascript/mastodon/reducers/timelines.js
+++ b/app/javascript/mastodon/reducers/timelines.js
@@ -1,9 +1,9 @@
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import {
- ACCOUNT_BLOCK_SUCCESS,
- ACCOUNT_MUTE_SUCCESS,
- ACCOUNT_UNFOLLOW_SUCCESS,
+ blockAccountSuccess,
+ muteAccountSuccess,
+ unfollowAccountSuccess
} from '../actions/accounts';
import {
TIMELINE_UPDATE,
@@ -200,11 +200,11 @@ export default function timelines(state = initialState, action) {
return deleteStatus(state, action.id, action.references, action.reblogOf);
case TIMELINE_CLEAR:
return clearTimeline(state, action.timeline);
- case ACCOUNT_BLOCK_SUCCESS:
- case ACCOUNT_MUTE_SUCCESS:
- return filterTimelines(state, action.relationship, action.statuses);
- case ACCOUNT_UNFOLLOW_SUCCESS:
- return filterTimeline('home', state, action.relationship, action.statuses);
+ case blockAccountSuccess.type:
+ case muteAccountSuccess.type:
+ return filterTimelines(state, action.payload.relationship, action.payload.statuses);
+ case unfollowAccountSuccess.type:
+ return filterTimeline('home', state, action.payload.relationship, action.payload.statuses);
case TIMELINE_SCROLL_TOP:
return updateTop(state, action.timeline, action.top);
case TIMELINE_CONNECT:
diff --git a/app/javascript/mastodon/reducers/user_lists.js b/app/javascript/mastodon/reducers/user_lists.js
index 089899398e..2f17fed5fd 100644
--- a/app/javascript/mastodon/reducers/user_lists.js
+++ b/app/javascript/mastodon/reducers/user_lists.js
@@ -33,8 +33,8 @@ import {
FOLLOW_REQUESTS_EXPAND_REQUEST,
FOLLOW_REQUESTS_EXPAND_SUCCESS,
FOLLOW_REQUESTS_EXPAND_FAIL,
- FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
- FOLLOW_REQUEST_REJECT_SUCCESS,
+ authorizeFollowRequestSuccess,
+ rejectFollowRequestSuccess,
} from '../actions/accounts';
import {
BLOCKS_FETCH_REQUEST,
@@ -66,11 +66,7 @@ import {
MUTES_EXPAND_SUCCESS,
MUTES_EXPAND_FAIL,
} from '../actions/mutes';
-import {
- NOTIFICATIONS_UPDATE,
-} from '../actions/notifications';
-
-
+import { notificationsUpdate } from '../actions/notifications';
const initialListState = ImmutableMap({
next: null,
@@ -163,8 +159,8 @@ export default function userLists(state = initialState, action) {
case FAVOURITES_FETCH_FAIL:
case FAVOURITES_EXPAND_FAIL:
return state.setIn(['favourited_by', action.id, 'isLoading'], false);
- case NOTIFICATIONS_UPDATE:
- return action.notification.type === 'follow_request' ? normalizeFollowRequest(state, action.notification) : state;
+ case notificationsUpdate.type:
+ return action.payload.notification.type === 'follow_request' ? normalizeFollowRequest(state, action.payload.notification) : state;
case FOLLOW_REQUESTS_FETCH_SUCCESS:
return normalizeList(state, ['follow_requests'], action.accounts, action.next);
case FOLLOW_REQUESTS_EXPAND_SUCCESS:
@@ -175,9 +171,9 @@ export default function userLists(state = initialState, action) {
case FOLLOW_REQUESTS_FETCH_FAIL:
case FOLLOW_REQUESTS_EXPAND_FAIL:
return state.setIn(['follow_requests', 'isLoading'], false);
- case FOLLOW_REQUEST_AUTHORIZE_SUCCESS:
- case FOLLOW_REQUEST_REJECT_SUCCESS:
- return state.updateIn(['follow_requests', 'items'], list => list.filterNot(item => item === action.id));
+ case authorizeFollowRequestSuccess.type:
+ case rejectFollowRequestSuccess.type:
+ return state.updateIn(['follow_requests', 'items'], list => list.filterNot(item => item === action.payload.id));
case BLOCKS_FETCH_SUCCESS:
return normalizeList(state, ['blocks'], action.accounts, action.next);
case BLOCKS_EXPAND_SUCCESS:
diff --git a/app/javascript/mastodon/selectors/accounts.ts b/app/javascript/mastodon/selectors/accounts.ts
new file mode 100644
index 0000000000..66193136c4
--- /dev/null
+++ b/app/javascript/mastodon/selectors/accounts.ts
@@ -0,0 +1,47 @@
+import { Record as ImmutableRecord } from 'immutable';
+import { createSelector } from 'reselect';
+
+import { accountDefaultValues } from 'mastodon/models/account';
+import type { Account, AccountShape } from 'mastodon/models/account';
+import type { Relationship } from 'mastodon/models/relationship';
+import type { RootState } from 'mastodon/store';
+
+const getAccountBase = (state: RootState, id: string) =>
+ state.accounts.get(id, null);
+
+const getAccountRelationship = (state: RootState, id: string) =>
+ state.relationships.get(id, null);
+
+const getAccountMoved = (state: RootState, id: string) => {
+ const movedToId = state.accounts.get(id)?.moved;
+
+ if (!movedToId) return undefined;
+
+ return state.accounts.get(movedToId);
+};
+
+interface FullAccountShape extends Omit {
+ relationship: Relationship | null;
+ moved: Account | null;
+}
+
+const FullAccountFactory = ImmutableRecord({
+ ...accountDefaultValues,
+ moved: null,
+ relationship: null,
+});
+
+export function makeGetAccount() {
+ return createSelector(
+ [getAccountBase, getAccountRelationship, getAccountMoved],
+ (base, relationship, moved) => {
+ if (base === null) {
+ return null;
+ }
+
+ return FullAccountFactory(base)
+ .set('relationship', relationship)
+ .set('moved', moved ?? null);
+ },
+ );
+}
diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js
index 0968fb090b..8a07ba774d 100644
--- a/app/javascript/mastodon/selectors/index.js
+++ b/app/javascript/mastodon/selectors/index.js
@@ -5,23 +5,7 @@ import { toServerSideType } from 'mastodon/utils/filters';
import { me } from '../initial_state';
-const getAccountBase = (state, id) => state.getIn(['accounts', id], null);
-const getAccountCounters = (state, id) => state.getIn(['accounts_counters', id], null);
-const getAccountRelationship = (state, id) => state.getIn(['relationships', id], null);
-const getAccountMoved = (state, id) => state.getIn(['accounts', state.getIn(['accounts', id, 'moved'])]);
-
-export const makeGetAccount = () => {
- return createSelector([getAccountBase, getAccountCounters, getAccountRelationship, getAccountMoved], (base, counters, relationship, moved) => {
- if (base === null) {
- return null;
- }
-
- return base.merge(counters).withMutations(map => {
- map.set('relationship', relationship);
- map.set('moved', moved);
- });
- });
-};
+export { makeGetAccount } from "./accounts";
const getFilters = (state, { contextType }) => {
if (!contextType) return null;
diff --git a/app/javascript/mastodon/store/store.ts b/app/javascript/mastodon/store/store.ts
index 6350885680..9f43f58a43 100644
--- a/app/javascript/mastodon/store/store.ts
+++ b/app/javascript/mastodon/store/store.ts
@@ -35,6 +35,5 @@ export const store = configureStore({
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType;
-// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;
export type GetState = typeof store.getState;
diff --git a/app/javascript/mastodon/utils/environment.ts b/app/javascript/mastodon/utils/environment.ts
new file mode 100644
index 0000000000..b6371499f6
--- /dev/null
+++ b/app/javascript/mastodon/utils/environment.ts
@@ -0,0 +1,7 @@
+export function isDevelopment() {
+ return process.env.NODE_ENV === 'development';
+}
+
+export function isProduction() {
+ return process.env.NODE_ENV === 'production';
+}
diff --git a/app/javascript/types/resources.ts b/app/javascript/types/resources.ts
deleted file mode 100644
index f3901ad150..0000000000
--- a/app/javascript/types/resources.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import type { Record } from 'immutable';
-
-type CustomEmoji = Record<{
- shortcode: string;
- static_url: string;
- url: string;
-}>;
-
-type AccountField = Record<{
- name: string;
- value: string;
- verified_at: string | null;
-}>;
-
-interface AccountApiResponseValues {
- acct: string;
- avatar: string;
- avatar_static: string;
- bot: boolean;
- created_at: string;
- discoverable: boolean;
- display_name: string;
- emojis: CustomEmoji[];
- fields: AccountField[];
- followers_count: number;
- following_count: number;
- group: boolean;
- header: string;
- header_static: string;
- id: string;
- last_status_at: string;
- locked: boolean;
- note: string;
- statuses_count: number;
- url: string;
- uri: string;
- username: string;
-}
-
-type NormalizedAccountField = Record<{
- name_emojified: string;
- value_emojified: string;
- value_plain: string;
-}>;
-
-interface NormalizedAccountValues {
- display_name_html: string;
- fields: NormalizedAccountField[];
- note_emojified: string;
- note_plain: string;
-}
-
-export type Account = Record<
- AccountApiResponseValues & NormalizedAccountValues
->;
diff --git a/app/lib/activitypub/parser/status_parser.rb b/app/lib/activitypub/parser/status_parser.rb
index 75b8f3d5c3..510f00f075 100644
--- a/app/lib/activitypub/parser/status_parser.rb
+++ b/app/lib/activitypub/parser/status_parser.rb
@@ -53,7 +53,8 @@ class ActivityPub::Parser::StatusParser
end
def created_at
- @object['published']&.to_datetime
+ datetime = @object['published']&.to_datetime
+ datetime if datetime.present? && (0..9999).cover?(datetime.year)
rescue ArgumentError
nil
end
diff --git a/app/lib/content_security_policy.rb b/app/lib/content_security_policy.rb
new file mode 100644
index 0000000000..e8fcf76a65
--- /dev/null
+++ b/app/lib/content_security_policy.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+class ContentSecurityPolicy
+ def base_host
+ Rails.configuration.x.web_domain
+ end
+
+ def assets_host
+ url_from_configured_asset_host || url_from_base_host
+ end
+
+ def media_host
+ cdn_host_value || assets_host
+ end
+
+ private
+
+ def url_from_configured_asset_host
+ Rails.configuration.action_controller.asset_host
+ end
+
+ def cdn_host_value
+ s3_alias_host || s3_cloudfront_host || azure_alias_host || s3_hostname_host
+ end
+
+ def url_from_base_host
+ host_to_url(base_host)
+ end
+
+ def host_to_url(host_string)
+ uri_from_configuration_and_string(host_string) if host_string.present?
+ end
+
+ def s3_alias_host
+ host_to_url ENV.fetch('S3_ALIAS_HOST', nil)
+ end
+
+ def s3_cloudfront_host
+ host_to_url ENV.fetch('S3_CLOUDFRONT_HOST', nil)
+ end
+
+ def azure_alias_host
+ host_to_url ENV.fetch('AZURE_ALIAS_HOST', nil)
+ end
+
+ def s3_hostname_host
+ host_to_url ENV.fetch('S3_HOSTNAME', nil)
+ end
+
+ def uri_from_configuration_and_string(host_string)
+ Addressable::URI.parse("#{host_protocol}://#{host_string}").tap do |uri|
+ uri.path += '/' unless uri.path.blank? || uri.path.end_with?('/')
+ end.to_s
+ end
+
+ def host_protocol
+ Rails.configuration.x.use_https ? 'https' : 'http'
+ end
+end
diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb
index 5885af882a..d7bf2327bc 100644
--- a/app/models/trends/statuses.rb
+++ b/app/models/trends/statuses.rb
@@ -106,7 +106,7 @@ class Trends::Statuses < Trends::Base
private
def eligible?(status)
- status.public_visibility? && status.account.discoverable? && !status.account.silenced? && (status.spoiler_text.blank? || Setting.trending_status_cw) && !status.sensitive? && !status.reply? && valid_locale?(status.language)
+ status.public_visibility? && status.account.discoverable? && !status.account.silenced? && !status.account.sensitized? && (status.spoiler_text.blank? || Setting.trending_status_cw) && !status.sensitive? && !status.reply? && valid_locale?(status.language)
end
def calculate_scores(statuses, at_time)
diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb
index 3b14a6748a..48167873e1 100644
--- a/app/services/fan_out_on_write_service.rb
+++ b/app/services/fan_out_on_write_service.rb
@@ -8,6 +8,7 @@ class FanOutOnWriteService < BaseService
# @param [Hash] options
# @option options [Boolean] update
# @option options [Array] silenced_account_ids
+ # @option options [Boolean] skip_notifications
def call(status, options = {})
@status = status
@account = status.account
@@ -37,8 +38,11 @@ class FanOutOnWriteService < BaseService
def fan_out_to_local_recipients!
deliver_to_self!
- notify_mentioned_accounts!
- notify_about_update! if update?
+
+ unless @options[:skip_notifications]
+ notify_mentioned_accounts!
+ notify_about_update! if update?
+ end
case @status.visibility.to_sym
when :public, :unlisted, :private
diff --git a/app/views/admin/settings/appearance/show.html.haml b/app/views/admin/settings/appearance/show.html.haml
index 89eddfdc42..37a5d7e0c7 100644
--- a/app/views/admin/settings/appearance/show.html.haml
+++ b/app/views/admin/settings/appearance/show.html.haml
@@ -11,7 +11,16 @@
%p.lead= t('admin.settings.appearance.preamble')
.fields-group
- = f.input :flavour_and_skin, collection: Themes.instance.flavours_and_skins, group_label_method: ->(flavour_and_skin) { I18n.t("flavours.#{flavour_and_skin}.name", default: flavour_and_skin) }, wrapper: :with_label, label: t('admin.settings.flavour_and_skin.title'), include_blank: false, as: :grouped_select, label_method: :last, value_method: ->(value) { value.join('/') }, group_method: :last
+ = f.input :flavour_and_skin,
+ collection: Themes.instance.flavours_and_skins,
+ group_label_method: ->(flavour_and_skin) { I18n.t("flavours.#{flavour_and_skin}.name", default: flavour_and_skin) },
+ wrapper: :with_label,
+ label: t('admin.settings.flavour_and_skin.title'),
+ include_blank: false,
+ as: :grouped_select,
+ label_method: :last,
+ value_method: ->(value) { value.join('/') },
+ group_method: :last
.fields-group
= f.input :custom_css, wrapper: :with_block_label, as: :text, input_html: { rows: 8 }
diff --git a/app/workers/thread_resolve_worker.rb b/app/workers/thread_resolve_worker.rb
index 3206c45f63..d4cefb3fdc 100644
--- a/app/workers/thread_resolve_worker.rb
+++ b/app/workers/thread_resolve_worker.rb
@@ -7,13 +7,18 @@ class ThreadResolveWorker
sidekiq_options queue: 'pull', retry: 3
def perform(child_status_id, parent_url, options = {})
- child_status = Status.find(child_status_id)
- parent_status = FetchRemoteStatusService.new.call(parent_url, **options.deep_symbolize_keys)
+ child_status = Status.find(child_status_id)
+ return if child_status.in_reply_to_id.present?
+
+ parent_status = ActivityPub::TagManager.instance.uri_to_resource(parent_url, Status)
+ parent_status ||= FetchRemoteStatusService.new.call(parent_url, **options.deep_symbolize_keys)
return if parent_status.nil?
child_status.thread = parent_status
child_status.save!
+
+ DistributionWorker.perform_async(child_status_id, { 'skip_notifications' => true }) if child_status.within_realtime_window?
rescue ActiveRecord::RecordNotFound
true
end
diff --git a/babel.config.js b/babel.config.js
index f53e5918cb..9ced748a96 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -7,8 +7,8 @@ module.exports = (api) => {
};
const envOptions = {
- loose: true,
- modules: false,
+ useBuiltIns: "usage",
+ corejs: { version: "3.30" },
debug: false,
include: [
'transform-numeric-separator',
@@ -18,29 +18,14 @@ module.exports = (api) => {
],
};
- const config = {
- presets: [
- '@babel/preset-typescript',
- ['@babel/react', reactOptions],
- ['@babel/env', envOptions],
- ],
- plugins: [
- ['formatjs'],
- 'preval',
- ],
- overrides: [
- {
- test: /tesseract\.js/,
- presets: [
- ['@babel/env', { ...envOptions, modules: 'commonjs' }],
- ],
- },
- ],
- };
+ const plugins = [
+ ['formatjs'],
+ 'preval',
+ ];
switch (env) {
case 'production':
- config.plugins.push(...[
+ plugins.push(...[
'lodash',
[
'transform-react-remove-prop-types',
@@ -63,14 +48,33 @@ module.exports = (api) => {
],
]);
break;
+
case 'development':
reactOptions.development = true;
envOptions.debug = true;
- break;
- case 'test':
- envOptions.modules = 'commonjs';
+
+ // We need Babel to not inject polyfills in dev, as this breaks `preval` files
+ envOptions.useBuiltIns = false;
+ envOptions.corejs = undefined;
break;
}
+ const config = {
+ presets: [
+ '@babel/preset-typescript',
+ ['@babel/react', reactOptions],
+ ['@babel/env', envOptions],
+ ],
+ plugins,
+ overrides: [
+ {
+ test: /tesseract\.js/,
+ presets: [
+ ['@babel/env', { ...envOptions, modules: 'commonjs' }],
+ ],
+ },
+ ],
+ };
+
return config;
};
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 41d0ee25b7..2c6099623d 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -2,6 +2,15 @@
require 'devise/strategies/authenticatable'
+# TODO: Remove this patch when this PR or similar is merged into Devise:
+# https://github.com/heartcombo/devise/pull/5645
+# We rely on ENV vars and not secrets/credentials, so the deprecation is just noise.
+class Devise::SecretKeyFinder
+ def find
+ @application.secret_key_base
+ end
+end
+
Warden::Manager.after_set_user except: :fetch do |user, warden|
session_id = warden.cookies.signed['_session_id'] || warden.raw_session['auth_id']
session_id = user.activate_session(warden.request) unless user.session_activations.active?(session_id)
diff --git a/config/initializers/json_ld.rb b/config/initializers/json_ld.rb
deleted file mode 100644
index 3ed3c4b31a..0000000000
--- a/config/initializers/json_ld.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-require_relative '../../lib/json_ld/security'
-require_relative '../../lib/json_ld/identity'
diff --git a/lib/json_ld/identity.rb b/config/initializers/json_ld_identity.rb
similarity index 100%
rename from lib/json_ld/identity.rb
rename to config/initializers/json_ld_identity.rb
diff --git a/lib/json_ld/security.rb b/config/initializers/json_ld_security.rb
similarity index 100%
rename from lib/json_ld/security.rb
rename to config/initializers/json_ld_security.rb
diff --git a/config/locales/activerecord.he.yml b/config/locales/activerecord.he.yml
index 54d0b0a1cc..211d984863 100644
--- a/config/locales/activerecord.he.yml
+++ b/config/locales/activerecord.he.yml
@@ -9,7 +9,7 @@ he:
agreement: הסכם שירות
email: כתובת דוא"ל
locale: הגדרות אזוריות
- password: סיסמא
+ password: סיסמה
user/account:
username: שם משתמש/ת
user/invite_request:
diff --git a/config/locales/ar.yml b/config/locales/ar.yml
index f8c74207de..f43d1ad2a6 100644
--- a/config/locales/ar.yml
+++ b/config/locales/ar.yml
@@ -578,6 +578,7 @@ ar:
total_reported: تقارير عنهم
total_storage: الوسائط المُرفَقة
totals_time_period_hint_html: المجموع المعروض في الأسفل يشمل بيانات منذ البداية.
+ unknown_instance: لا يوجد حاليا أي تسجيل لهذا النطاق على هذا الخادم.
invites:
deactivate_all: تعطيلها كافة
filter:
@@ -1112,6 +1113,11 @@ ar:
hint_html: شيء واحد آخر! نحن بحاجة إلى التأكّد من أنك إنسان (حتى نتمكن من تتفادي البريد المزعج!). حل رمز CAPTCHA أدناه وانقر فوق "متابعة".
title: التحقق من الأمان
confirmations:
+ awaiting_review: تمّ تأكيد عنوان بريدك الإلكتروني! موظفو %{domain} يعاينونَ تسجيلكَ حاليًا. ستتلقى بريدًا إلكترونيًا إن تَمّ قُبولك!
+ awaiting_review_title: التسجيل الخاص بك قيد المُعاينة
+ clicking_this_link: اضغط على هذا الرابط
+ login_link: تسجيل الدخول
+ proceed_to_login_html: يمكنكَ الآن الاستمرار إلى %{login_link}.
wrong_email_hint: إذا كان عنوان البريد الإلكتروني هذا غير صحيح، يمكنك تغييره في إعدادات الحساب.
delete_account: احذف الحساب
delete_account_html: إن كنت ترغب في حذف حسابك يُمكنك المواصلة هنا. سوف يُطلَبُ منك التأكيد قبل الحذف.
diff --git a/config/locales/bg.yml b/config/locales/bg.yml
index b1d91875b3..04b4d438bb 100644
--- a/config/locales/bg.yml
+++ b/config/locales/bg.yml
@@ -534,6 +534,7 @@ bg:
total_reported: Доклади за тях
total_storage: Прикачена мултимедия
totals_time_period_hint_html: Общите стойности, показани по-долу, включват данни за всички времена.
+ unknown_instance: В момента няма запис на този домейн на този сървър.
invites:
deactivate_all: Деактивиране на всички
filter:
@@ -1040,6 +1041,14 @@ bg:
hint_html: Просто още едно нещо! Трябва да потвърдим, че сте човек (това е с цел предпазване на нежелани съобщения!). Разгадайте капчата долу и щракнете на "Продължаване".
title: Проверка за сигурност
confirmations:
+ awaiting_review: Вашият адрес на е-поща е потвърден! Служителите на %{domain} сега преглеждат регистрацията ви. Ще получите е-писмо, ако одобрят акаунта ви!
+ awaiting_review_title: Вашата регистрация се преглежда
+ clicking_this_link: щракване на тази връзка
+ login_link: влизане
+ proceed_to_login_html: Сега може да пристъпите към %{login_link}.
+ redirect_to_app_html: Трябва да сте пренасочени към приложението %{app_name}. Ако не се случи това, то опитайте %{clicking_this_link} или ръчно се върнете към приложението.
+ registration_complete: Вашата регистрация на %{domain} вече завърши!
+ welcome_title: Добре дошли, %{name}!
wrong_email_hint: Ако този адрес на е-поща не е правилен, то може да го промените в настройки на акаунта.
delete_account: Изтриване на акаунта
delete_account_html: Ако желаете да изтриете акаунта си, може да сторите това тук. Ще ви се поиска потвърждение.
@@ -1101,6 +1110,7 @@ bg:
functional: Вашият акаунт е в изправност.
pending: Вашето приложение чака преглед от нашия екип. Това може да отнеме време. Ще получите имейл, ако приложението е одобрено.
redirecting_to: Вашият акаунт е бездеен, защото сега се пренасочва към %{acct}.
+ self_destruct: Затваряйки %{domain}, ще получите само ограничен достъп до акаунта си.
view_strikes: Преглед на предишните предупреждения против акаунта ви
too_fast: Образецът подаден пребързо, опитайте пак.
use_security_key: Употреба на ключ за сигурност
@@ -1570,6 +1580,9 @@ bg:
over_daily_limit: Завишили сте ограничението от %{limit} планирани публикации за днес
over_total_limit: Завишили сте ограничението от %{limit} планирани публикации
too_soon: Заплануваната дата трябва да е в бъдеще
+ self_destruct:
+ lead_html: За жалост, %{domain} е трайно затворен. Ако сте имали там акаунт, то няма да може да продължите да го употребявате, но още може да заявите резервно копие на данните си.
+ title: Този сървър се затваря
sessions:
activity: Последна активност
browser: Браузър
diff --git a/config/locales/cy.yml b/config/locales/cy.yml
index baa6d31e35..846ce41def 100644
--- a/config/locales/cy.yml
+++ b/config/locales/cy.yml
@@ -1,7 +1,7 @@
---
cy:
about:
- about_mastodon_html: 'Rhwydwaith cymdeithasol y dyfodol: Dim hysbysebion, dim gwyliadwriaeth gorfforaethol, dylunio moesegol, a datganoli! Chi sy berchen eich data gyda Mastodon!'
+ about_mastodon_html: 'Rhwydwaith cymdeithasol y dyfodol: Dim hysbysebion, dim gwyliadwriaeth gorfforaethol, dylunio moesegol a datganoli! Chi sy berchen eich data gyda Mastodon!'
contact_missing: Heb ei osodF
contact_unavailable: Ddim yn berthnasol
hosted_on: Mastodon wedi ei weinyddu ar %{domain}
@@ -1113,6 +1113,14 @@ cy:
hint_html: Un peth arall! Mae angen i ni gadarnhau eich bod yn ddynol (mae hyn er mwyn i ni allu cadw'r sbam allan!). Datryswch y CAPTCHA isod a chliciwch "Parhau".
title: Gwiriad diogelwch
confirmations:
+ awaiting_review: Mae eich cyfeiriad e-bost wedi'i gadarnhau! Mae aelod o staff %{domain} wrthi'n adolygu'ch cofrestriad. Byddwch yn derbyn e-bost os ydyn nhw'n cymeradwyo eich cyfrif!
+ awaiting_review_title: Mae eich cofrestriad yn cael ei adolygu
+ clicking_this_link: clicio ar y ddolen hon
+ login_link: mewngofnodi
+ proceed_to_login_html: Gallwch nawr symud ymlaen i %{login_link}.
+ redirect_to_app_html: Dylech fod wedi cael eich ailgyfeirio i ap %{app_name}. Os na ddigwyddodd hynny, rhowch gynnig ar %{clicking_this_link} neu ewch eich hun i'r ap.
+ registration_complete: Mae eich cofrestriad ar %{domain} bellach wedi'i gwblhau!
+ welcome_title: Croeso, %{name}!
wrong_email_hint: Os nad yw'r cyfeiriad e-bost hwnnw'n gywir, gallwch ei newid yng ngosodiadau'r cyfrif.
delete_account: Dileu cyfrif
delete_account_html: Os hoffech chi ddileu eich cyfrif, mae modd parhau yma. Bydd gofyn i chi gadarnhau.
diff --git a/config/locales/devise.he.yml b/config/locales/devise.he.yml
index 0f389bd383..e45f62b031 100644
--- a/config/locales/devise.he.yml
+++ b/config/locales/devise.he.yml
@@ -8,10 +8,10 @@ he:
failure:
already_authenticated: חשבון זה כבר מחובר.
inactive: חשבון זה טרם הופעל.
- invalid: "%{authentication_keys} או סיסמא לא נכונים."
+ invalid: "%{authentication_keys} או סיסמה לא נכונים."
last_attempt: יש לך עוד ניסיון אחד לפני נעילת החשבון.
locked: חשבון זה נעול.
- not_found_in_database: "%{authentication_keys} או סיסמא לא נכונים."
+ not_found_in_database: "%{authentication_keys} או סיסמה לא נכונים."
pending: חשבונך נמצא עדיין בבדיקה.
timeout: פג תוקף השהיה בחשבון. נא להכנס מחדש על מנת להמשיך.
unauthenticated: יש להרשם או להכנס לחשבון על מנת להמשיך.
@@ -27,24 +27,24 @@ he:
title: אימות כתובת דוא״ל
email_changed:
explanation: 'כתובת הדוא"ל של חשבונך שונתה ל:'
- extra: אם לא שינית את כתובת הדוא"ל שלך, יכול להיות שמישהו השתלט על חשבונך. נא לשנות את הסיסמא מיידית או ליצור קשר עם מנהלי השרת אם ננעלת מחוץ לחשבון.
+ extra: אם לא שינית את כתובת הדוא"ל שלך, יכול להיות שמישהו השתלט על חשבונך. נא לשנות את הסיסמה שלך מיידית או ליצור קשר עם מנהלי השרת אם ננעלת מחוץ לחשבונך.
subject: 'מסטודון: כתובת הדוא"ל שונתה'
title: כתובת דוא״ל חדשה
password_change:
- explanation: הסיסמא לחשבונך שונתה.
- extra: אם לא שינית את סיסמתך, יכול להיות שמישהו השתלט על חשבונך. נא לשנות את הסיסמא מיידית או ליצור קשר עם מנהלי השרת אם ננעלת מחוץ לחשבון.
- subject: 'מסטודון: הסיסמא שונתה'
- title: הסיסמא שונתה
+ explanation: הסיסמה לחשבונך שונתה.
+ extra: אם לא שינית את סיסמתך, יכול להיות שמישהו השתלט על חשבונך. נא לשנות את הסיסמה שלך מיידית או ליצור קשר עם מנהלי השרת אם ננעלת מחוץ לחשבונך.
+ subject: 'מסטודון: הסיסמה שונתה'
+ title: הסיסמה שונתה
reconfirmation_instructions:
explanation: נא לאמת את הכתובת הדוא"ל החדשה על מנת לשנותה.
extra: אם שינוי זה לא בוצע על ידך, נא להתעלם מדוא"ל זה. כתובת הדוא"ל של חשבון המסטודון שלך לא תשונה אלא אם תלחץ הקישורית לעיל.
subject: 'מסטודון: נא לאשר כתובת דוא"ל עבור %{instance}'
title: אימות כתובת דוא״ל
reset_password_instructions:
- action: שינוי סיסמא
- explanation: ביקשת סיסמא חדשה לחשבון.
- extra: אם לא ביקשת את זה, נא להתעלם מדוא"ל זה. סיסמתך לא תשתנה עוד שתלחץ הקישורית לעיל ותיוצר סיסמא חדשה.
- subject: 'מסטודון: הוראות לאיפוס סיסמא'
+ action: שינוי סיסמה
+ explanation: ביקשת סיסמה חדשה לחשבון שלך.
+ extra: אם לא ביקשת זאת, נא להתעלם מדוא"ל זה. סיסמתך לא תשתנה עוד שתלחץ הקישורית לעיל ותיוצר סיסמה חדשה.
+ subject: 'מסטודון: הוראות לאיפוס סיסמה'
title: איפוס סיסמה
two_factor_disabled:
explanation: האימות הדו-גורמי לחשבונך בוטל. ניתן עתה להכנס לחשבון עם כתובת דוא"ל וסיסמא בלבד.
@@ -81,7 +81,7 @@ he:
failure: 'לא ניתן לאמת את חשבונך מ־%{kind} מהסיבה: "%{reason}".'
success: נכשל אימות מחשבון %{kind}.
passwords:
- no_token: לא ניתן לגשת לעמוד זה, אלא מדוא"ל איפוס סיסמא. אם לא הגעת מדוא"ל איפוס סיסמא, יש לוודא שכתובת הקישורית הוקלדה בשלמותה.
+ no_token: לא ניתן לגשת לעמוד זה, אלא מדוא"ל איפוס סיסמה. אם הגעת מדוא"ל איפוס סיסמה, יש לוודא שכתובת הקישורית הוקלדה בשלמותה.
send_instructions: בדקות הקרובות יתקבל דוא"ל עם הוראות לאיפוס סיסמתך. יש לבדוק את תיבת הספאם ליתר בטחון אם ההודעה לא הגיעה תוך דקות ספורות.
send_paranoid_instructions: אם כתובת הדוא"ל שלך קיימת במסד הנתונים, יתקבל בדקות הקרובות דוא"ל עם הוראות לאחזור סיסמא. יש לבדוק את תיבת הספאם ליתר בטחון אם ההודעה לא הגיעה תוך דקות ספורות.
updated: סיסמתך שונתה בהצלחה. הינך כעת במצב מחובר.
diff --git a/config/locales/doorkeeper.hr.yml b/config/locales/doorkeeper.hr.yml
index cb48de3135..abf07ab723 100644
--- a/config/locales/doorkeeper.hr.yml
+++ b/config/locales/doorkeeper.hr.yml
@@ -35,8 +35,11 @@ hr:
scopes: Odvojite opsege razmacima. Za korištenje zadanih opsega, ostavite prazno.
index:
application: Aplikacija
+ delete: Obriši
+ empty: Nemaš aplikacija.
name: Ime
new: Nova aplikacija
+ show: Prikaži
title: Vaše aplikacije
new:
title: Nova aplikacija
@@ -60,6 +63,7 @@ hr:
confirmations:
revoke: Jeste li sigurni?
index:
+ authorized_at: Autorizirano %{date}
title: Vaše autorizirane aplikacije
errors:
messages:
@@ -88,6 +92,14 @@ hr:
authorized_applications:
destroy:
notice: Aplikacija je opozvana.
+ grouped_scopes:
+ title:
+ favourites: Favoriti
+ filters: Filteri
+ follows: Praćeni
+ lists: Liste
+ search: Traži
+ statuses: Objave
layouts:
admin:
nav:
@@ -95,6 +107,7 @@ hr:
application:
title: Traži se OAuth autorizacija
scopes:
+ admin:read: pročitaj sve podatke na serveru
follow: mijenjati odnose između računa
read: čitati sve podatke Vašeg računa
write: mijenjati sve podatke Vašeg računa
diff --git a/config/locales/doorkeeper.sl.yml b/config/locales/doorkeeper.sl.yml
index 8fe39bbf61..a613308b28 100644
--- a/config/locales/doorkeeper.sl.yml
+++ b/config/locales/doorkeeper.sl.yml
@@ -4,7 +4,7 @@ sl:
attributes:
doorkeeper/application:
name: Ime programa
- redirect_uri: Preusmeritev URI
+ redirect_uri: URI za preusmeritev
scopes: Obsegi
website: Spletišče programa
errors:
@@ -19,7 +19,7 @@ sl:
doorkeeper:
applications:
buttons:
- authorize: Overi
+ authorize: Odobri
cancel: Prekliči
destroy: Uniči
edit: Uredi
@@ -55,23 +55,23 @@ sl:
title: 'Program: %{name}'
authorizations:
buttons:
- authorize: Overi
+ authorize: Odobri
deny: Zavrni
error:
title: Prišlo je do napake
new:
prompt_html: "%{client_name} želi dovoljenje za dostop do vašega računa. Gre za zunanji program. Če mu ne zaupate, mu ne dodelite teh pravic."
- review_permissions: Preglej pravice
- title: Potrebna je pooblastitev
+ review_permissions: Preglej dovoljenja
+ title: Potrebna je odobritev
show:
- title: Kopirajte to pooblastilno kodo in jo prilepite v program.
+ title: Kopirajte to odobritveno kodo in jo prilepite v program.
authorized_applications:
buttons:
revoke: Prekliči
confirmations:
revoke: Ali ste prepričani?
index:
- authorized_at: Overjen(a) %{date}
+ authorized_at: Odobreno %{date}
description_html: To so programi, ki lahko dostopajo do vašega računa prek vmesnika API. Če so na seznamu programi, ki jih ne prepoznate ali pa se čudno vedejo, lahko prekličete njihovo pravico do dostopa.
last_used_at: Zadnjič uporabljeno %{date}
never_used: Nikoli uporabljeno
@@ -80,14 +80,14 @@ sl:
title: Vaši odobreni programi
errors:
messages:
- access_denied: Lastnik virov ali strežnik pooblastil je zavrnil zahtevo.
+ access_denied: Lastnik virov ali odobritveni strežnik je zavrnil zahtevo.
credential_flow_not_configured: Pretok geselskih pooblastil lastnika virov ni uspel, ker Doorkeeper.configure.resource_owner_from_credentials ni nastavljen.
- invalid_client: Overitev odjemalca ni uspela zaradi neznanega odjemalca, zaradi nevključitve overitve odjemalca ali zaradi nepodprte metode overitve.
- invalid_grant: Predložena odobritev za pooblastilo je neveljavna, potekla, preklicana, se ne ujema z URI preusmeritvijo, ki je uporabljena v zahtevi za pooblastilo ali je bila izdana drugemu odjemalcu.
+ invalid_client: Odobritev odjemalca ni uspela zaradi neznanega odjemalca, zaradi nevključitve odobritve odjemalca ali zaradi nepodprte metode odobritve.
+ invalid_grant: Predložena odobritev je neveljavna, je potekla, je preklicana, se ne ujema z URI-jem za preusmeritev uporabljenim v zahtevi za odobritev, ali pa je bila izdana drugemu odjemalcu.
invalid_redirect_uri: URI za preusmeritev ni veljaven.
invalid_request:
missing_param: 'Zahtevani parameter manjka: %{value}.'
- request_not_authorized: Zahtevo je potrebno overiti. Zahtevani parameter za overjanje zahteve manjka ali ni veljaven.
+ request_not_authorized: Zahtevo je potrebno odobriti. Zahtevani parameter za odobritev zahteve manjka ali ni veljaven.
unknown: Zahtevku manjka zahtevani parameter, vključuje nepodprto vrednost parametra ali je nepravilno oblikovan.
invalid_resource_owner: Predložene poverilnice lastnika virov niso veljavne ali pa lastnika virov ni mogoče najti
invalid_scope: Zahtevani obseg je neveljaven, neznan ali nepravilen.
@@ -96,11 +96,11 @@ sl:
revoked: Žeton za dostop je bil preklican
unknown: Žeton za dostop je neveljaven
resource_owner_authenticator_not_configured: Iskanje lastnika virov ni uspelo, ker Doorkeeper.configure.resource_owner_authenticator ni nastavljen.
- server_error: Strežnik pooblastil je naletel na nepričakovano stanje, ki je preprečilo, da bi izpolnil zahtevo.
- temporarily_unavailable: Strežnik pooblastil, zaradi začasne preobremenitve ali vzdrževanja, trenutno ne more obdelati zahteve.
- unauthorized_client: Odjemalec nima pooblastila za izvajanje te zahteve po tej metodi.
- unsupported_grant_type: Strežnik pooblastil ne podpira vrste odobritve pooblastila.
- unsupported_response_type: Strežnik pooblastil ne podpira te vrste odziva.
+ server_error: Odobritveni strežnik je naletel na nepričakovano stanje, ki je preprečilo, da bi izpolnil zahtevo.
+ temporarily_unavailable: Odobritveni strežnik zaradi začasne preobremenitve ali vzdrževanja trenutno ne more obdelati zahteve.
+ unauthorized_client: Odjemalec nima odobritve za izvajanje te zahteve po tej metodi.
+ unsupported_grant_type: Odobritveni strežnik ne podpira zahtevane vrste odobritve.
+ unsupported_response_type: Odobritveni strežnik pooblastil ne podpira te vrste odziva.
flash:
applications:
create:
@@ -145,7 +145,7 @@ sl:
applications: Programi
oauth2_provider: Ponudnik OAuth2
application:
- title: Potrebna je pooblastitev OAuth
+ title: Potrebna je odobritev OAuth
scopes:
admin:read: preberi vse podatke na strežniku
admin:read:accounts: preberi občutljive informacije vseh računov
diff --git a/config/locales/es.yml b/config/locales/es.yml
index aab31747e7..d071e19a12 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -1044,7 +1044,11 @@ es:
awaiting_review: "¡Tu dirección de correo electrónico ha sido confirmada! El personal de %{domain} está revisando tu registro. ¡Recibirás un correo electrónico cuando aprueben tu cuenta!"
awaiting_review_title: Estamos revisando tu registro
clicking_this_link: haciendo clic en este enlace
+ login_link: iniciar sesión
+ proceed_to_login_html: Ahora puedes proceder a %{login_link}.
+ redirect_to_app_html: Serás redirigido a la aplicación %{app_name}. Si esto no sucede, prueba %{clicking_this_link} o regresa manualmente a la aplicación.
registration_complete: "¡Has completado tu registro en %{domain}!"
+ welcome_title: "¡Bienvenido, %{name}!"
wrong_email_hint: Si esa dirección de correo electrónico no es correcta, puedes cambiarla en la configuración de la cuenta.
delete_account: Borrar cuenta
delete_account_html: Si desea eliminar su cuenta, puede proceder aquí. Será pedido de una confirmación.
diff --git a/config/locales/fi.yml b/config/locales/fi.yml
index 4b4585f690..0f670847f4 100644
--- a/config/locales/fi.yml
+++ b/config/locales/fi.yml
@@ -534,7 +534,7 @@ fi:
total_reported: Niitä koskevat raportit
total_storage: Medialiitteet
totals_time_period_hint_html: Alla näkyvät yhteenlasketut tiedot sisältävät koko ajan.
- unknown_instance: Tällä palvelimella ei ole tällä hetkellä tähän verkkotunnukseen liittyviä tietueita.
+ unknown_instance: Tällä palvelimella ei tällä hetkellä ole tähän verkkotunnukseen liittyviä tietueita.
invites:
deactivate_all: Poista kaikki käytöstä
filter:
@@ -1041,13 +1041,13 @@ fi:
hint_html: Vielä yksi juttu! Meidän on vahvistettava, että olet ihminen (tämän avulla pidämme roskapostin poissa!). Ratkaise alla oleva CAPTCHA-vahvistus ja paina "Jatka".
title: Turvatarkastus
confirmations:
- awaiting_review: Sähköpostiosoitteesi on vahvistettu! Palvelun %{domain} ylläpito tarkistaa nyt rekisteröitymisesi. Saat sähköpostiviestin, jos tilisi hyväksytään!
+ awaiting_review: Sähköpostiosoitteesi on vahvistettu! Seuraavaksi palvelimen %{domain} ylläpito tarkistaa rekisteröitymisesi ja saat lopuksi ilmoituksen sähköpostitse, jos tilisi hyväksytään!
awaiting_review_title: Rekisteröitymisesi on tarkistettavana
- clicking_this_link: napsauttaa tätä linkkiä
+ clicking_this_link: tästä linkistä
login_link: kirjautumalla sisään
proceed_to_login_html: Voit nyt jatkaa %{login_link}.
- redirect_to_app_html: Sinun olisi pitänyt ohjautua sovellukseen %{app_name}. Jos näin ei tapahtunut, kokeile %{clicking_this_link} tai palaa sovellukseen manuaalisesti.
- registration_complete: Rekisteröitymisesi palveluun %{domain} on nyt valmis!
+ redirect_to_app_html: Sinun olisi pitänyt ohjautua sovellukseen %{app_name}. Jos näin ei tapahtunut, yritä avata se %{clicking_this_link} tai palaa sovellukseen manuaalisesti.
+ registration_complete: Rekisteröitymisesi palvelimelle %{domain} on suoritettu!
welcome_title: Tervetuloa, %{name}!
wrong_email_hint: Jos sähköpostiosoite ei ole oikein, voit muuttaa sen tilin asetuksista.
delete_account: Poista tili
diff --git a/config/locales/he.yml b/config/locales/he.yml
index d987931f1e..2bd9f89c71 100644
--- a/config/locales/he.yml
+++ b/config/locales/he.yml
@@ -1134,7 +1134,7 @@ he:
new_confirmation_instructions_sent: אתם עומדים לקבל הודעת דואל חדשה עם קיש/ור אימות בדקות הקרובות!
title: בדוק/בדקי את תיבת הדואר הנכנס שלך
sign_in:
- preamble_html: הכנס.י עם שם וסיסמא מאתר %{domain}. אם חשבונך מתארח בשרת אחר, לא ניתן להתחבר איתו פה.
+ preamble_html: הכנס.י עם שם וסיסמה מאתר %{domain}. אם חשבונך מתארח בשרת אחר, לא ניתן להתחבר איתו פה.
title: התחבר אל %{domain}
sign_up:
manual_review: פתיחת חשבון אצל %{domain} עוברת בדיקה ידנית על ידי הצוות שלנו. כדי לסייע בתהליך הרישום שלכןם, כתבו לנו על עצמכןם ולמה אתןם רוצותים חשבון בשרת %{domain}.
diff --git a/config/locales/ko.yml b/config/locales/ko.yml
index 1bcc8853e5..dc1b0d1f49 100644
--- a/config/locales/ko.yml
+++ b/config/locales/ko.yml
@@ -1025,14 +1025,14 @@ ko:
hint_html: 하나만 더! 당신이 사람인지 확인이 필요합니다 (스팸 계정을 거르기 위해서 필요한 과정입니다). 아래에 있는 CAPTCHA를 풀고 "계속"을 누르세요
title: 보안 체크
confirmations:
- awaiting_review: 이메일 주소를 확인했어요! 이제 %{domain} 스태프가 가입을 검토해요. 계정이 승인되면 이메일을 보내드려요.
- awaiting_review_title: 가입 검토 중
+ awaiting_review: 이메일 주소가 확인되었습니다! 이제 %{domain} 스태프가 가입을 검토할 것입니다. 계정이 승인되면 이메일을 받게 됩니다!
+ awaiting_review_title: 가입 신청을 검토 중입니다
clicking_this_link: 이 링크를 클릭
login_link: 로그인
- proceed_to_login_html: "%{login_link} 할 수 있게 되었어요."
- redirect_to_app_html: 곧 %{app_name}으로 리디렉션 되어요. 안 된다면, %{clicking_this_link}하거나 직접 앱으로 돌아가세요.
- registration_complete: 지금 막 %{domain} 가입을 마쳤어요!
- welcome_title: "%{name} 님 반가워요!"
+ proceed_to_login_html: 이제 %{login_link} 할 수 있습니다.
+ redirect_to_app_html: 곧 %{app_name}으로 리디렉션 됩니다. 안 된다면, %{clicking_this_link}하거나 직접 앱으로 돌아가세요.
+ registration_complete: 지금 막 %{domain} 가입이 완료되었습니다!
+ welcome_title: "%{name} 님 반갑습니다!"
wrong_email_hint: 만약 이메일 주소가 올바르지 않다면, 계정 설정에서 수정할 수 있습니다.
delete_account: 계정 삭제
delete_account_html: 계정을 삭제하고 싶은 경우, 여기서 삭제할 수 있습니다. 삭제 전 확인 화면이 표시됩니다.
diff --git a/config/locales/ms.yml b/config/locales/ms.yml
index 6d1ededbc4..951b04194e 100644
--- a/config/locales/ms.yml
+++ b/config/locales/ms.yml
@@ -306,6 +306,7 @@ ms:
unpublish: Nyahterbit
unpublished_msg: Pengumuman berjaya dinyahterbitkan!
updated_msg: Pengumuman berjaya dikemaskini!
+ critical_update_pending: Kemas kini kritikal belum selesai
custom_emojis:
assign_category: Menugaskan kategori
by_domain: Domain
@@ -522,6 +523,7 @@ ms:
total_reported: Laporan tentang mereka
total_storage: Lampiran media
totals_time_period_hint_html: Jumlah yang dipaparkan di bawah termasuk data untuk sepanjang masa.
+ unknown_instance: Pada masa ini tiada rekod domain ini pada pelayan ini.
invites:
deactivate_all: Nyahaktifkan semua
filter:
@@ -756,10 +758,26 @@ ms:
approved: Kelulusan diperlukan untuk pendaftaran
none: Tiada siapa boleh mendaftar
open: Sesiapapun boleh mendaftar
+ security:
+ authorized_fetch: Memerlukan pengesahan daripada pelayan bersekutu
+ authorized_fetch_overridden_hint: Pada masa ini anda tidak dapat menukar tetapan ini kerana ia ditindih oleh pemboleh ubah persekitaran.
+ federation_authentication: Penguatkuasaan pengesahan persekutuan
title: Tetapan server
site_uploads:
delete: Hapuskan fail yang dimuat naik
destroyed_msg: Muat naik tapak berjaya dihapuskan!
+ software_updates:
+ critical_update: Penting — sila kemas kini dengan segera
+ description: Disarankan untuk memastikan pemasangan Mastodon anda dikemas kini bagi mendapat manfaat daripada pembaikan dan ciri terkini. Selain itu, kadangkala penting untuk mengemas kini Mastodon tepat pada masanya untuk mengelakkan isu keselamatan. Atas sebab ini, Mastodon menyemak kemas kini setiap 30 minit dan akan memberitahu anda mengikut keutamaan pemberitahuan e-mel anda.
+ documentation_link: Ketahui lebih lanjut
+ release_notes: Catatan keluaran
+ title: Kemas kini tersedia
+ type: Jenis
+ types:
+ major: Keluaran utama
+ minor: Keluaran kecil
+ patch: Keluaran tampung — pembetulan pepijat dan perubahan yang mudah diterapkan
+ version: Versi
statuses:
account: Penulis
application: Aplikasi
@@ -807,10 +825,10 @@ ms:
elasticsearch_index_mismatch:
message_html: Pemetaan indeks Elasticsearch sudah lapuk. Sila jalankan tootctl search deploy --only=%{value}
elasticsearch_preset:
- action: Lihat dokumentasi
- message_html: Kelompok Elasticsearch anda mempunyai lebih daripada satu nod, tetapi Mastodon tidak dikonfigurasikan untuk menggunakannya.
+ action: Lihat pendokumenan
+ message_html: Kelompok Elasticsearch anda mempunyai lebih daripada satu nod, tetapi Mastodon tidak ditatarajah untuk menggunakannya.
elasticsearch_preset_single_node:
- action: Lihat dokumentasi
+ action: Lihat pendokumenan
message_html: Kelompok Elasticsearch anda hanya mempunyai satu nod, ES_PRESET hendaklah ditetapkan kepada single_node_cluster.
elasticsearch_reset_chewy:
message_html: Indeks sistem Elasticsearch anda sudah lapuk kerana perubahan tetapan. Sila jalankan tootctl search deploy --reset-chewy untuk mengemas kininya.
@@ -824,6 +842,12 @@ ms:
message_html: Anda belum menentukan sebarang peraturan server.
sidekiq_process_check:
message_html: Tiada proses Sidekiq berjalan untuk baris gilir %{value}. Sila semak konfigurasi Sidekiq anda
+ software_version_critical_check:
+ action: Lihat kemas kini yang tersedia
+ message_html: Kemas kini kritikal Mastodon telah tersedia, sila kemas kini secepat yang mungkin.
+ software_version_patch_check:
+ action: Lihat kemas kini yang tersedia
+ message_html: Kemas kini pembetulan pepijat Mastodon telah tersedia.
upload_check_privacy_error:
action: Semak di sini untuk maklumat lanjut
message_html: "Server web anda salah konfigurasi. Privasi pengguna anda berisiko"
@@ -933,6 +957,9 @@ ms:
body: "%{target} sedang merayu keputusan penyederhanaan sebanyak %{action_taken_by} dari %{date}, iaitu %{type}. Mereka tulis:"
next_steps: Anda boleh meluluskan rayuan untuk membuat asal keputusan penyederhanaan atau mengabaikannya.
subject: "%{username} sedang merayu keputusan penyederhanaan pada %{instance}"
+ new_critical_software_updates:
+ body: Versi kritikal baharu Mastodon telah dikeluarkan, anda mungkin ingin mengemas kini secepat yang mungkin!
+ subject: Kemas kini kritikal Mastodon telah tersedia untuk %{instance}!
new_pending_account:
body: Butiran akaun baharu ada di bawah. Anda boleh meluluskan atau menolak aplikasi ini.
subject: Akaun baharu disediakan untuk semakan pada %{instance} (%{username})
@@ -940,6 +967,9 @@ ms:
body: "%{reporter} telah melaporkan %{target}"
body_remote: Seseorang daripada %{domain} telah melaporkan %{target}
subject: Laporan baharu untuk %{instance} (#%{id})
+ new_software_updates:
+ body: Versi baharu Mastodon telah dikeluarkan, anda mungkin mahu mengemas kini!
+ subject: Versi baharu Mastodon telah tersedia untuk %{instance}!
new_trends:
body: 'Item berikut memerlukan semakan sebelum boleh dipaparkan secara terbuka:'
new_trending_links:
@@ -1053,6 +1083,7 @@ ms:
functional: Akaun anda beroperasi sepenuhnya.
pending: Permohonan anda sedang menunggu semakan oleh kakitangan kami. Ini mungkin mengambil sedikit masa. Anda akan menerima e-mel sekiranya permohonan anda diluluskan.
redirecting_to: Akaun anda tidak aktif kerana ia sedang mengubah hala ke %{acct}.
+ self_destruct: Memandangkan %{domain} akan ditutup, anda hanya akan mendapat capaian terhad kepada akaun anda.
view_strikes: Lihat pelanggaran yang lepas terhadap akaun anda
too_fast: Borang diserahkan terlalu cepat, cuba lagi.
use_security_key: Gunakan kunci keselamatan
@@ -1504,6 +1535,9 @@ ms:
over_daily_limit: Anda telah melebihi had %{limit} pos berjadual untuk hari ini
over_total_limit: Anda telah melebihi had %{limit} pos berjadual
too_soon: Tarikh yang dijadualkan mestilah pada masa hadapan
+ self_destruct:
+ lead_html: Malangnya, %{domain} akan ditutup secara kekal. Jika anda mempunyai akaun di situ, anda tidak akan dapat terus menggunakannya, tetapi anda masih boleh meminta sandaran data anda.
+ title: Pelayan ini akan ditutup
sessions:
activity: Aktiviti terakhir
browser: Pelayar
@@ -1666,9 +1700,10 @@ ms:
default: "%b %d, %Y, %H:%M"
month: "%b %Y"
time: "%H:%M"
+ with_time_zone: "%d %b %Y, %H:%M %Z"
translation:
errors:
- quota_exceeded: Kuota penggunaan seluruh server untuk perkhidmatan terjemahan telah melebihi.
+ quota_exceeded: Kuota penggunaan seluruh pelayan untuk perkhidmatan terjemahan telah berlebihan.
too_many_requests: Terdapat terlalu banyak permintaan kepada perkhidmatan terjemahan baru-baru ini.
two_factor_authentication:
add: Tambah
diff --git a/config/locales/my.yml b/config/locales/my.yml
index 8e01e82afe..d8e83543c6 100644
--- a/config/locales/my.yml
+++ b/config/locales/my.yml
@@ -523,6 +523,7 @@ my:
total_reported: "၎င်းတို့နှင့်ဆိုင်သော အစီရင်ခံစာများ"
total_storage: မီဒီယာ ပူးတွဲချက်များ
totals_time_period_hint_html: အောက်တွင်ဖော်ပြထားသော စုစုပေါင်းမှာ အချိန်တိုင်းအတွက် အချက်အလက်များဖြစ်သည်။
+ unknown_instance: လောလောဆယ် ဤဆာဗာတွင် ဤဒိုမိန်း၏ မှတ်တမ်းမရှိပါ။
invites:
deactivate_all: အားလုံးပယ်ဖျက်ရန်
filter:
@@ -1006,6 +1007,13 @@ my:
hint_html: နောက်ထပ်တစ်ခုသာ။ သင်သည် လူသားဖြစ်ကြောင်း ကျွန်ုပ်တို့ အတည်ပြုရန် လိုအပ်ပါသည် (စပမ်းများကို ရှောင်ရှားနိုင်စေရန် အတွက်ဖြစ်ပါသည်။) အောက်ပါ CAPTCHA ကိုဖြေရှင်းပြီး "Continue" ကို နှိပ်ပါ။
title: လုံခြုံရေးစစ်ဆေးမှု
confirmations:
+ awaiting_review: သင့်အီးမေးလ်လိပ်စာကို အတည်ပြုပြီးပါပြီ။ %{domain} စီမံသူများမှ ယခု သင်စာရင်းသွင်းခြင်းကို ပြန်လည်သုံးသပ်နေပါသည်။ သင့်အကောင့်ကို အတည်ပြုပါက အီးမေးလ်တစ်စောင် လက်ခံရရှိမည်ဖြစ်သည်။
+ awaiting_review_title: သင် စာရင်သွင်းထားခြင်းကို စစ်ဆေးနေပါသည်
+ clicking_this_link: ဤလင့်ခ်ကို နှိပ်ပါ
+ login_link: အကောင့်ဝင်ရန်
+ proceed_to_login_html: သင် ယခု %{login_link} သို့ ဆက်သွားနိုင်ပါပြီ။
+ registration_complete: "%{domain} တွင် သင် စာရင်းသွင်းခြင်းမှာ မှန်ကန်ပါပြီ။"
+ welcome_title: ကြိုဆိုပါတယ် %{name}။
wrong_email_hint: ထိုအီးမေးလ်လိပ်စာ မမှန်ပါက အကောင့်သတ်မှတ်ချက်များတွင် ပြောင်းလဲနိုင်သည်။
delete_account: အကောင့်ဖျက်ပါ
delete_account_html: သင့်အကောင့်ဖျက်လိုပါကဤနေရာတွင် ဆက်လက်လုပ်ဆောင်နိုင်သည်။ အတည်ပြုချက်တောင်းပါမည်။
@@ -1067,6 +1075,7 @@ my:
functional: သင့်အကောင့်မှာ အပြည့်အဝလုပ်ဆောင်နေပါပြီ။
pending: သင့်အက်ပလီကေးရှင်းကို ကျွန်ုပ်တို့၏ဝန်ထမ်းများမှ ပြန်လည်သုံးသပ်နေပါသည်။ အချိန်အနည်းငယ်ကြာနိုင်ပါသည်။ သင့်အက်ပလီကေးရှင်းကို အတည်ပြုပြီးပါက အီးမေးလ်တစ်စောင် သင် လက်ခံရရှိမည်ဖြစ်သည်။
redirecting_to: သင့်အကောင့်မှာ လက်ရှိတွင် %{acct} သို့ ပြန်ညွှန်းနေသောကြောင့် သုံးစွဲ၍မရပါ။
+ self_destruct: "%{domain} ပိတ်သွားသောကြောင့် သင့်အကောင့်သို့ အကန့်အသတ်ဖြင့်သာ ဝင်ရောက်နိုင်မည်ဖြစ်သည်။"
view_strikes: သင့်အကောင့်ကို ဆန့်ကျင်သည့် ယခင်ကလုပ်ဆောင်ချက်များကို ကြည့်ပါ
too_fast: ဖောင်တင်သည်မှာ မြန်နေပါသည်။ ထပ်စမ်းကြည့်ပါ။
use_security_key: လုံခြုံရေးကီးကို သုံးပါ
@@ -1525,6 +1534,8 @@ my:
over_daily_limit: ယနေ့အတွက် စီစဉ်ထားသည့် ပို့စ်များ၏ ကန့်သတ်ချက် %{limit} ကို ကျော်လွန်သွားပါပြီ
over_total_limit: စီစဉ်ထားသည့် ပို့စ်များ၏ ကန့်သတ်ချက် %{limit} ကို ကျော်လွန်သွားပါပြီ
too_soon: စီစဉ်ထားသောရက်စွဲမှာ အနာဂတ်အတွက်ဖြစ်သည်
+ self_destruct:
+ title: ဤဆာဗာ ပိတ်ထားပါသည်
sessions:
activity: နောက်ဆုံးလုပ်ဆောင်ချက်
browser: ဘရောက်ဇာ
diff --git a/config/locales/nl.yml b/config/locales/nl.yml
index d8a1c88656..2a8a59d764 100644
--- a/config/locales/nl.yml
+++ b/config/locales/nl.yml
@@ -1041,14 +1041,14 @@ nl:
hint_html: Nog maar één ding! Je moet bevestigen dat je een mens bent (dit is om de spam buiten de deur te houden!). Los de onderstaande CAPTCHA op en klik op "Doorgaan".
title: Veiligheidscontrole
confirmations:
- awaiting_review: Je e-mailadres is bevestigd! De %{domain}-medewerkers zijn nu bezig met het bekijken van jouw registratie. Je ontvangt een e-mailbericht als ze jouw account goedkeuren!
+ awaiting_review: Je e-mailadres is bevestigd! De medewerkers van %{domain} zijn nu bezig met het beoordelen van jouw registratie. Je ontvangt een e-mailbericht wanneer ze jouw account goedkeuren!
awaiting_review_title: Je registratie wordt beoordeeld
- clicking_this_link: klik op deze koppeling
- login_link: aanmelden
+ clicking_this_link: op deze link te klikken
+ login_link: inloggen
proceed_to_login_html: Je kunt nu verder gaan naar %{login_link}.
redirect_to_app_html: Je zou omgeleid moeten zijn naar de %{app_name} app. Als dat niet is gebeurd, probeer dan %{clicking_this_link} of keer handmatig terug naar de app.
registration_complete: Je registratie op %{domain} is nu voltooid!
- welcome_title: Welkom, %{name}!
+ welcome_title: Welkom %{name}!
wrong_email_hint: Als dat e-mailadres niet correct is, kun je het wijzigen in je accountinstellingen.
delete_account: Account verwijderen
delete_account_html: Wanneer je jouw account graag wilt verwijderen, kun je dat hier doen. We vragen jou daar om een bevestiging.
@@ -1581,8 +1581,8 @@ nl:
over_total_limit: Je hebt de limiet van %{limit} in te plannen berichten overschreden
too_soon: De datum voor het ingeplande bericht moet in de toekomst liggen
self_destruct:
- lead_html: Helaas gaat %{domain} permanent afsluiten. Als u daar een account had, kunt u deze niet meer gebruiken, maar u kunt nog steeds een back-up van uw gegevens opvragen.
- title: Deze server gaat afsluiten
+ lead_html: Helaas gaat %{domain} permanent sluiten. Als je daar een account had, kun je deze niet meer gebruiken, maar je kunt nog steeds een back-up van je gegevens opvragen.
+ title: Deze server gaat sluiten
sessions:
activity: Laatst actief
browser: Webbrowser
diff --git a/config/locales/oc.yml b/config/locales/oc.yml
index 8145002e56..83c2638b51 100644
--- a/config/locales/oc.yml
+++ b/config/locales/oc.yml
@@ -474,6 +474,9 @@ oc:
warning: Mèfi ! Agachatz de partejar aquela donada amb degun !
your_token: Vòstre geton d’accès
auth:
+ confirmations:
+ clicking_this_link: en clicant aqueste ligam
+ welcome_title: La benvenguda %{name} !
delete_account: Suprimir lo compte
delete_account_html: Se volètz suprimir vòstre compte, podètz o far aquí. Vos demandarem que confirmetz.
description:
diff --git a/config/locales/pl.yml b/config/locales/pl.yml
index 08df6e7fc9..e02cad0395 100644
--- a/config/locales/pl.yml
+++ b/config/locales/pl.yml
@@ -1077,6 +1077,14 @@ pl:
hint_html: Jeszcze jedno! Potrzebujemy potwierdzić twoje człowieczeństwo, żeby ograniczyć spam. Rozwiąż poniższą CAPTCHA-ę i naciśnij "Kontynuuj".
title: Kontrola bezpieczeństwa
confirmations:
+ awaiting_review: Twój adres e-mail został potwierdzony! Administracja %{domain} sprawdza Twoją rejestrację. Otrzymasz e-mail w momencie, gdy zaakceptują Twoje konto!
+ awaiting_review_title: Twoja rejestracja jest obecnie sprawdzana
+ clicking_this_link: kliknąć ten link
+ login_link: zaloguj się
+ proceed_to_login_html: Teraz możesz przejść do %{login_link}.
+ redirect_to_app_html: Powinieneś zostać przekierowany do aplikacji %{app_name}. Jeśli tak się nie stało, spróbuj %{clicking_this_link} lub ręcznie wróć do aplikacji.
+ registration_complete: Twoja rejestracja na %{domain} została zakończona!
+ welcome_title: Witaj, %{name}!
wrong_email_hint: Jeśli ten adres e-mail nie jest poprawny, możesz go zmienić w ustawieniach konta.
delete_account: Usunięcie konta
delete_account_html: Jeżeli chcesz usunąć konto, przejdź tutaj. Otrzymasz prośbę o potwierdzenie.
diff --git a/config/locales/simple_form.he.yml b/config/locales/simple_form.he.yml
index d8d47fee61..581a66807f 100644
--- a/config/locales/simple_form.he.yml
+++ b/config/locales/simple_form.he.yml
@@ -180,9 +180,9 @@ he:
bot: זהו חשבון מסוג בוט
chosen_languages: סינון שפות
confirm_new_password: אישור סיסמא חדשה
- confirm_password: אישור סיסמא
+ confirm_password: אישור סיסמה
context: סינון לפי הקשר
- current_password: סיסמא נוכחית
+ current_password: סיסמה נוכחית
data: מידע
display_name: שם להצגה
email: כתובת דוא"ל
@@ -194,10 +194,10 @@ he:
irreversible: הסרה במקום הסתרה
locale: שפה
max_uses: מספר מרבי של שימושים
- new_password: סיסמא חדשה
+ new_password: סיסמה חדשה
note: אודות
otp_attempt: קוד אימות דו-שלבי
- password: סיסמא
+ password: סיסמה
phrase: מילת מפתח או ביטוי
setting_advanced_layout: אפשר ממשק ווב מתקדם
setting_aggregate_reblogs: קבץ הדהודים זהים
diff --git a/config/locales/simple_form.ms.yml b/config/locales/simple_form.ms.yml
index c0d47ace0a..79929cec5d 100644
--- a/config/locales/simple_form.ms.yml
+++ b/config/locales/simple_form.ms.yml
@@ -6,10 +6,10 @@ ms:
discoverable: Siaran awam dan profil anda mungkin dipaparkan atau disyorkan dalam pelbagai kawasan Mastodon dan profil anda mungkin dicadangkan kepada pengguna lain.
display_name: Nama penuh anda atau nama anda yang menyeronokkan.
fields: Halaman utama anda, kata ganti nama, umur, apa sahaja yang anda mahukan.
- indexable: Pos awam anda mungkin muncul dalam hasil carian di Mastodon. Orang yang telah berinteraksi dengan pos anda mungkin boleh mencarinya tanpa mengira.
+ indexable: Kiriman awam anda mungkin muncul dalam hasil carian di Mastodon. Orang yang telah berinteraksi dengan kiriman anda mungkin boleh mencarinya.
note: 'Anda boleh @menyebut orang lain atau #hashtags.'
- show_collections: Orang akan dapat menyemak imbas mengikut dan pengikut anda. Orang yang anda ikuti akan melihat bahawa anda mengikuti mereka tanpa mengira.
- unlocked: Orang akan dapat mengikuti anda tanpa meminta kelulusan. Nyahtanda jika anda ingin menyemak permintaan ikuti dan pilih sama ada untuk menerima atau menolak pengikut baharu.
+ show_collections: Orang akan dapat menyemak imbas ikutan dan pengikut anda. Orang yang anda ikuti akan melihat bahawa anda tetap mengikuti mereka.
+ unlocked: Orang akan dapat mengikuti anda tanpa meminta kelulusan. Nyahtanda jika anda ingin menyemak permintaan ikutan dan pilih sama ada untuk menerima atau menolak pengikut baharu.
account_alias:
acct: Tentukan namapengguna@domain akaun yang ingin anda alihkan daripada
account_migration:
@@ -144,7 +144,7 @@ ms:
fields:
name: Label
value: Kandungan
- indexable: Sertakan pos awam dalam hasil carian
+ indexable: Termasuk kiriman awam dalam hasil carian
show_collections: Tunjukkan ikutan dan pengikut pada profil
unlocked: Terima pengikut baharu secara automatik
account_alias:
@@ -291,6 +291,12 @@ ms:
pending_account: Akaun baru memerlukan semakan
reblog: Seorang menggalakan hantaran anda
report: Laporan baru telah dihantar
+ software_updates:
+ all: Beritahu mengenai semua kemas kini
+ critical: Beritahu mengenai kemas kini kritikal sahaja
+ label: Versi baharu Mastodon kini tersedia
+ none: Tidak pernah memberitahu mengenai kemas kini (tidak disarankan)
+ patch: Beritahu mengenai kemas kini pembetulan pepijat
trending_tag: Trend baru memerlukan semakan
rule:
text: Peraturan
@@ -317,6 +323,7 @@ ms:
url: URL titik akhir
'no': Tidak
not_recommended: Tidak disyorkan
+ overridden: Ditindih
recommended: Disyorkan
required:
mark: "*"
diff --git a/config/locales/simple_form.sq.yml b/config/locales/simple_form.sq.yml
index 3256e7378d..dc07478070 100644
--- a/config/locales/simple_form.sq.yml
+++ b/config/locales/simple_form.sq.yml
@@ -256,8 +256,8 @@ sq:
site_contact_username: Emër përdoruesi kontakti
site_extended_description: Përshkrim i zgjeruar
site_short_description: Përshkrim shërbyesi
- site_terms: Rregulla Privatësie
- site_title: Emër shërbyesi
+ site_terms: Politika e privatësisë
+ site_title: Emri i serverit
status_page_url: URL faqeje gjendjesh
theme: Temë parazgjedhje
thumbnail: Miniaturë shërbyesi
diff --git a/config/locales/sk.yml b/config/locales/sk.yml
index f16803fb29..b3bc8c2dcd 100644
--- a/config/locales/sk.yml
+++ b/config/locales/sk.yml
@@ -585,6 +585,7 @@ sk:
title: Serverové pravidlá
settings:
about:
+ manage_rules: Spravuj serverové pravidlá
title: Ohľadom
appearance:
title: Vzhľad
@@ -607,9 +608,16 @@ sk:
approved: Pre registráciu je nutné povolenie
none: Nikto sa nemôže registrovať
open: Ktokoľvek sa môže zaregistrovať
+ title: Nastavenia servera
site_uploads:
delete: Vymaž nahratý súbor
destroyed_msg: Nahratie bolo zo stránky úspešne vymazané!
+ software_updates:
+ documentation_link: Zisti viac
+ title: Dostupné aktualizácie
+ types:
+ major: Hlavné vydanie
+ version: Verzia
statuses:
account: Autor
application: Aplikácia
diff --git a/config/locales/sl.yml b/config/locales/sl.yml
index 00c696f6fd..77ddfd6e2b 100644
--- a/config/locales/sl.yml
+++ b/config/locales/sl.yml
@@ -401,9 +401,11 @@ sl:
cancel: Prekliči
confirm: Suspendiraj
permanent_action: Z razveljavitvijo suzpenza ne boste obnovili nobenih podatkov ali razmerij.
+ preamble_html: Suspendirali boste %{domain} in njene poddomene.
remove_all_data: S tem boste odstranili celotno vsebino, medijske vsebine ter podatke iz profila za rčune te domene na vašem strežniku.
stop_communication: Vaš strežnik bo prenehal komunicirati s temi strežniki.
title: Potrdi domenski blok za %{domain}
+ undo_relationships: To bo prekinilo vse odnose sledenja med računi na teh strežnikih in na vašem strežniku.
created_msg: Domenski blok se sedaj obdeluje
destroyed_msg: Domenski blok je bil razveljavljen
domain: Domena
@@ -554,6 +556,7 @@ sl:
total_reported: Prijave o njih
total_storage: Predstavnostne priloge
totals_time_period_hint_html: Spodaj prikazani seštevki vključujejo podatke za celotno obdobje.
+ unknown_instance: Trenutno ne obstaja zapis te domene na tem strežniku.
invites:
deactivate_all: Onemogoči vse
filter:
@@ -767,6 +770,9 @@ sl:
branding:
preamble: Blagovna znamka vašega strežnika ga loči od drugih strežnikov v omrežju. Podatki se lahko prikžejo prek številnih okolij, kot so spletni vmesnik Mastodona, domorodni programi, predogledi povezav na drugih spletiščih, aplikacije za sporočanje itn. Zatorej je najbolje, da te podatke ohranite jasne, kratke in pomenljive.
title: Blagovne znamke
+ captcha_enabled:
+ desc_html: To se zanaša na zunanje skripte hCaptcha in lahko predstavlja tveganje za varnost in zasebnost. Poleg tega to lahko nekaterim ljudem (posebno invalidom) občutno oteži dostopnost registracijskega postopka. Zato svetujemo, da razmislite o drugih ukrepih, kot je na primer registracija na podlagi odobritve ali povabila.
+ title: Od novih uporabnikov zahtevaj reševanje CAPTCHA za potrditev računov
content_retention:
preamble: Nazdor nad hrambo vsebine uporabnikov v Mastodonu.
title: Hramba vsebin
@@ -795,13 +801,17 @@ sl:
none: Nihče se ne more prijaviti
open: Vsakdo se lahko prijavi
security:
+ authorized_fetch: Od drugih strežnikov v federaciji zahtevaj overitev pristnosti
+ authorized_fetch_hint: Zahtevanje overitve pristnosti od drugih strežnikov v federaciji omogoči strožje uveljavljanje uporabniških in strežniških blokad. Vendar je cena za to počasnejše delovanje, zmanjšanje dosega vaših odgovorov in morebitne težave z združljivostjo z nekaterimi storitvami v federaciji. Poleg tega to odločenim akterjem ne bo preprečilo pridobivanja vaših javnih objav in računov.
authorized_fetch_overridden_hint: Trenutno ne morete spremeniti te nastavitve, ker jo preglasi okoljska spremenljivka.
+ federation_authentication: Izvršba overitve pristnosti v federaciji
title: Nastavitve strežnika
site_uploads:
delete: Izbriši naloženo datoteko
destroyed_msg: Prenos na strežnik uspešno izbrisan!
software_updates:
critical_update: Kritično — čim prej posodobite
+ description: Vašo namestitev Mastodona je priporočeno vedno imeti posodobljeno in tako koristiti najnovejše popravke ter zmožnosti. Poleg tega je včasih nujno čim prej posodobiti Mastodon in se s tem izogniti varnostnim težavam. Zato Mastodon vsakih 30 minut preverja razpoložljivost posodobitev in vas o njih obvešča glede na vaše nastavitve obveščanja po e-pošti.
documentation_link: Več o tem
release_notes: Opombe ob izdaji
title: Razpoložljive posodobitve
@@ -851,10 +861,20 @@ sl:
system_checks:
database_schema_check:
message_html: Na čakanju so migracije zbirke podatkov. Prosimo, izvedite jih, da zagotovite, da se program vede pričakovano
+ elasticsearch_health_red:
+ message_html: Z gručo Elasticsearch ni vse v redu (rdeče stanje), zmožnosti iskanja niso na voljo
+ elasticsearch_health_yellow:
+ message_html: Z gručo Elasticsearch ni vse v redu (rumeno stanje), priporočeno je ugotoviti razlog
+ elasticsearch_index_mismatch:
+ message_html: Preslikave kazala Elasticsearch so zastarele. Poženite tootctl search deploy --only=%{value}
elasticsearch_preset:
action: Glejte dokumentacijo
+ message_html: Vaša gruča Elasticsearch vsebuje več kot eno vozlišče, vendar Mastodon ni nastavljen, da bi jih uporabljal.
elasticsearch_preset_single_node:
action: Glejte dokumentacijo
+ message_html: Vaša gruča Elasticsearch vsebuje samo eno vozlišče, ES_PRESET bi moralo biti nastavljeno na single_node_cluster.
+ elasticsearch_reset_chewy:
+ message_html: Sistemsko kazalo Elasticsearch je zastarelo zaradi spremembe nastavitve. Za posodobitev poženite tootctl search deploy --reset-chewy.
elasticsearch_running_check:
message_html: Povezava z Elasticsearch ni uspela. Preverite, da deluje, ali onemogočite iskanje po vsem besedilu
elasticsearch_version_check:
@@ -867,6 +887,7 @@ sl:
message_html: Noben proces Sidekiq ne poteka za %{value} vrst. Preglejte svojo prilagoditev Sidekiq
software_version_critical_check:
action: Glejte razpoložljive posodobitve
+ message_html: Na voljo je kritična posodobitev Mastodona. Posodobite čim prej.
software_version_patch_check:
action: Glejte razpoložljive posodobitve
message_html: Na voljo je posodobitev Mastodona s popravki hroščev.
@@ -991,6 +1012,9 @@ sl:
body: "%{target} se pritožuje na moderatorsko odločitev %{action_taken_by} z dne %{date}, ki je bila %{type}. Zapisal/a je:"
next_steps: Pritožbi lahko ugodite in s tem razveljavite moderatorsko odločitev ali pa jo prezrete.
subject: "%{username} se je pritožil na moderatorsko odločitev na %{instance}"
+ new_critical_software_updates:
+ body: Izdane so bile nove kritične različice Mastodona. Priporočena je čimprejšnja posodobitev.
+ subject: Za %{instance} so na voljo kritične posodobitve Mastodona!
new_pending_account:
body: Podrobnosti o novem računu so navedene spodaj. To aplikacijo lahko odobrite ali zavrnete.
subject: Nov račun za pregled na %{instance} (%{username})
@@ -998,6 +1022,9 @@ sl:
body: "%{reporter} je prijavil %{target}"
body_remote: Nekdo iz %{domain} je prijavil %{target}
subject: Nove prijave za %{instance} (#%{id})
+ new_software_updates:
+ body: Izdane so bile nove različice Mastodona. Priporočena je posodobitev.
+ subject: Za %{instance} so na voljo nove različice Mastodona.
new_trends:
body: 'Naslednji elementi potrebujejo pregled, preden jih je možno javno prikazati:'
new_trending_links:
@@ -1046,8 +1073,18 @@ sl:
auth:
apply_for_account: Zaprosite za račun
captcha_confirmation:
+ help_html: Če imate težave pri reševanju CAPTCHA, lahko prek %{email} stopite v stik z nami in pomagali vam bomo.
+ hint_html: Samo še nekaj. Moramo se prepričati, da ste človek (to nam pomaga pri preprečevanju neželenih vsebin). Rešite spodnji CAPTCHA in kliknite »Nadaljuj«.
title: Varnostno preverjanje
confirmations:
+ awaiting_review: Vaš e-poštni naslov je potrjen. Skrbniki %{domain} bodo pregledali vašo prijavo. Če odobrijo vaš račun, boste o tem prejeli e-pošto.
+ awaiting_review_title: Vaša prijava se pregleduje
+ clicking_this_link: s klikom na to povezavo
+ login_link: prijavo
+ proceed_to_login_html: Sedaj lahko nadaljujete na %{login_link}.
+ redirect_to_app_html: Morali bi biti preusmerjeni na aplikacijo %{app_name}. Če se to ni zgodilo, poskusite %{clicking_this_link} ali pa se ročno vrnite na aplikacijo.
+ registration_complete: Vaša prijava na %{domain} je sedaj zaključena.
+ welcome_title: Pozdravljeni, %{name}!
wrong_email_hint: Če ta e-poštni naslov ni pravilen, ga lahko spremenite v nastavitvah računa.
delete_account: Izbriši račun
delete_account_html: Če želite izbrisati svoj račun, lahko nadaljujete tukaj. Prosili vas bomo za potrditev.
@@ -1083,7 +1120,9 @@ sl:
rules:
accept: Sprejmi
back: Nazaj
+ invited_by: "%{domain} se lahko pridružite zahvaljujoč povabilu, ki ste ga prejeli od:"
preamble: Slednje določajo in njihovo spoštovanje zagotavljajo moderatorji %{domain}.
+ preamble_invited: Preden nadaljujete, si preberite osnovna pravila, ki so jih postavili moderatorji na %{domain}.
title: Nekaj osnovnih pravil.
title_invited: Ste povabljeni.
security: Varnost
@@ -1107,6 +1146,7 @@ sl:
functional: Vaš račun je polno opravilen.
pending: Naše osebje preverja vašo prijavo. To lahko traja nekaj časa. Če bo vaša prijava odobrena, boste prejeli e-pošto.
redirecting_to: Vaš račun ni dejaven, ker trenutno preusmerja na račun %{acct}.
+ self_destruct: Ker se %{domain} zapira, boste imeli omejen dostop da svojega računa.
view_strikes: Pokaži pretekle ukrepe proti mojemu računu
too_fast: Obrazec oddan prehitro, poskusite znova.
use_security_key: Uporabi varnostni ključ
@@ -1188,6 +1228,7 @@ sl:
invalid_domain: ni veljavno ime domene
edit_profile:
basic_information: Osnovni podatki
+ hint_html: "Prilagodite, kaj ljudje vidijo na vašem javnem profilu in poleg vaših objav. Drugi vam bodo raje sledili nazaj in z vami klepetali, če boste imeli izpolnjen profil in nastavljeno profilno sliko."
other: Drugo
errors:
'400': Zahteva, ki ste jo oddali, je neveljavna ali nepravilno oblikovana.
@@ -1322,6 +1363,20 @@ sl:
merge_long: Ohrani obstoječe zapise in dodaj nove
overwrite: Prepiši
overwrite_long: Zamenjaj trenutne zapise z novimi
+ overwrite_preambles:
+ blocking_html: Svoj seznam blokiranih računov boste nadomestili z največ %{total_items} računi iz %{filename}.
+ bookmarks_html: Svoje zaznamke boste nadomestili z največ %{total_items} objavami iz %{filename}.
+ domain_blocking_html: Svoj seznam blokiranih domen boste nadomestili z največ %{total_items} domenami iz %{filename}.
+ following_html: "Začeli boste slediti največ %{total_items} računom iz %{filename} in prenehali slediti vsem ostalim."
+ lists_html: Svoje sezname boste nadomestili z vsebino datoteke %{filename}. Največ %{total_items} računov bo dodanih na nove sezname.
+ muting_html: Svoj seznam utišanih računov boste nadomestili z največ %{total_items} računi iz %{filename}.
+ preambles:
+ blocking_html: "Blokirali boste največ %{total_items} računov iz %{filename}."
+ bookmarks_html: "Med zaznamke boste dodali boste največ %{total_items} objav iz %{filename}."
+ domain_blocking_html: "Blokirali boste največ %{total_items} domen iz %{filename}."
+ following_html: "Začeli boste slediti največ %{total_items} računom iz %{filename}."
+ lists_html: Dodali boste največ %{total_items} računov iz %{filename} na svoje sezname. Po potrebi bodo ustvarjeni novi seznami.
+ muting_html: "Utišali boste največ %{total_items} računov iz %{filename}."
preface: Podatke, ki ste jih izvozili iz drugega strežnika, lahko uvozite. Na primer seznam oseb, ki jih spremljate ali blokirate.
recent_imports: Nedavni uvozi
states:
@@ -1393,6 +1448,7 @@ sl:
unsubscribe:
action: Da, odjavi me
complete: Odjavljeni
+ confirmation_html: Ali se res želite odjaviti od prejemanja %{type} za Mastodon na %{domain} na svojo e-pošto %{email}? Kadarkoli se lahko znova prijavite iz svojih nastavitev e-poštnih obvestil.
emails:
notification_emails:
favourite: e-sporočil z obvestili o priljubljenosti
@@ -1400,6 +1456,7 @@ sl:
follow_request: e-sporočil o zahtevah za sledenje
mention: e-sporočil z obvestili o omembah
reblog: e-sporočil z obvestili o izpostavljanju
+ resubscribe_html: Če ste se odjavili po pomoti, se lahko znova prijavite iz svojih nastavitev e-poštnih obvestil.
success_html: Nič več ne boste prejemali %{type} za Mastodon na %{domain} na svoj e-naslov %{email}.
title: Odjavi od naročnine
media_attachments:
@@ -1526,9 +1583,13 @@ sl:
posting_defaults: Privzete nastavitev objavljanja
public_timelines: Javne časovnice
privacy:
+ hint_html: "Prilagodite, kako lahko drugi najdejo vaš profil in vaše objave. V Mastodonu obstaja več zmožnosti, ki vam pomagajo doseči širše občinstvo, če so omogočene. Vzemite si čas in preverite, ali te nastavitve ustrezajo vašemu namenu uporabe."
privacy: Zasebnost
+ privacy_hint_html: Nadzorujte, koliko informacij želite razkriti drugim. Ljudje lahko zanimive profile in aplikacije odkrijejo z brskanjem po seznamih sledenih in ko vidijo katere programe drugi uporabljajo za objavljanje. Morda pa bi to želeli skriti in varovati zasebnost.
reach: Dosegljivost
+ reach_hint_html: Nadzorujte, ali želite, da vas drugi ljudje najdejo in vam pričnejo slediti. Ali želite, da se vaše objave prikažejo na strani Razišči? Ali želite, da vas drugi ljudje vidijo med predlogi za sledenje? Ali želite nove sledilce odobriti samodejno, ali vsakega posebej odobriti ročno?
search: Iskanje
+ search_hint_html: Nadzorujte, kako želite, da vas najdejo. Ali želite, da vas ljudje najdejo po javnih objavah? Ali želite, da ljudje, ki niso na Mastodonu, lahko najdejo vaš profil med iskanjem po spletu? Vedite, da javnih objav in podatkov ni mogoče povsem izvzeti iz podatkovnih zbirk vseh spletnih iskalnikov.
title: Zasebnost in dosegljivost
privacy_policy:
title: Pravilnik o zasebnosti
@@ -1571,6 +1632,9 @@ sl:
over_daily_limit: Za ta dan ste presegli omejitev %{limit} načrtovanih objav
over_total_limit: Presegli ste omejitev %{limit} načrtovanih objav
too_soon: Načrtovani datum mora biti v prihodnosti
+ self_destruct:
+ lead_html: Na žalost se %{domain} za vedno zapira. Če ste tu imeli svoj račun, ga v prihodnje ne boste mogli več uporabljati. Zahtevate lahko kopijo svojih podatkov.
+ title: Ta strežnik se zapira
sessions:
activity: Zadnja dejavnost
browser: Brskalnik
@@ -1752,6 +1816,10 @@ sl:
month: "%b %Y"
time: "%H:%M"
with_time_zone: "%d. %b. %Y %H:%M %Z"
+ translation:
+ errors:
+ quota_exceeded: Kvota uporabe prevajalne storitve za ta strežnik je bila presežena.
+ too_many_requests: V zadnjem času je prevajalna storitev prejela preveč zahtevkov.
two_factor_authentication:
add: Dodaj
disable: Onemogoči
@@ -1837,7 +1905,9 @@ sl:
seamless_external_login: Prijavljeni ste prek zunanje storitve, tako da nastavitve gesla in e-pošte niso na voljo.
signed_in_as: 'Vpisani kot:'
verification:
+ extra_instructions_html: Nasvet: Povezava na vaši spletni strani je lahko nevidna. Pomembni del je atribut rel="me", ki preprečuje lažno predstavljanje na spletnih straneh z uporabniško ustvarjeno vsebino. Namesto oznake a lahko uporabite tudi oznako link znotraj glave (head) spletne strani, vendar mora biti HTML dosegljiv brez izvajanja skript JavaScript.
here_is_how: Kako to poteka
+ hint_html: "Vsakdo lahko potrdi svojo istovetnost na Mastodonu. To temelji na odprtih spletnih standardih in je sedaj in za vedno brezplačno. Potrebujete le osebno spletno stran, po kateri vas ljudje prepoznajo. Ko na svoj profil dodate povezavo na to osebno spletno stran, bo Mastodon preveril, ali na njej obstaja povezava nazaj na profil. Če ta obstaja, bo to vidno na profiu."
instructions_html: Spodnjo kodo kopirajte in prilepite v HTML svojega spletnega mesta. Nato dodajte naslov svoje spletne strani v eno od dodatnih polj v svojem profilu v zavihku »Uredi profil« in shranite spremembe.
verification: Potrditev
verified_links: Vaše preverjene povezave
diff --git a/config/locales/sq.yml b/config/locales/sq.yml
index 74810b147a..e4fb811ce3 100644
--- a/config/locales/sq.yml
+++ b/config/locales/sq.yml
@@ -1035,6 +1035,14 @@ sq:
hint_html: Edhe një gjë tjetër! Na duhet të ripohoni se jeni qenie njerëzore (që të mbajmë larg mesazhe të padëshiruar!). Zgjidhni CAPTCHA-n më poshtë dhe klikoni mbi “Vazhdo”.
title: Kontroll sigurie
confirmations:
+ awaiting_review: Adresa juaj email u ripohua! Ekipi i %{domain} stani po bën regjistrimin tuaj. Nëse e miratojnë llogarinë tuaj, do të merrni një email!
+ awaiting_review_title: Regjistrimi juaj po merret në shqyrtim
+ clicking_this_link: duke klikuar këtë lidhje
+ login_link: hyni
+ proceed_to_login_html: Tani mund të vazhdoni të %{login_link}.
+ redirect_to_app_html: Duhet të ishit ridrejtuar te aplikacioni %{app_name}. Nëse s’ndodhi, provoni %{clicking_this_link}, ose të ktheheni dorazi te aplikacioni.
+ registration_complete: Tanimë është plotësuar regjistrimi juaj në %{domain}!
+ welcome_title: Mirë se vini, %{name}!
wrong_email_hint: Nëse ajo adresë email s’është e saktë, mund ta ndryshoni te rregullimet e llogarisë.
delete_account: Fshije llogarinë
delete_account_html: Nëse dëshironi të fshihni llogarinë tuaj, mund ta bëni që këtu. Do t’ju kërkohet ta ripohoni.
diff --git a/config/locales/sv.yml b/config/locales/sv.yml
index 1d84f8a6af..a6ee12ba27 100644
--- a/config/locales/sv.yml
+++ b/config/locales/sv.yml
@@ -1044,6 +1044,8 @@ sv:
awaiting_review_title: Din registrering är under granskning
clicking_this_link: klicka på denna länk
login_link: logga in
+ proceed_to_login_html: Du kan nu fortsätta med att %{login_link}.
+ redirect_to_app_html: Du borde ha omdirigerats till appen %{app_name}. Om det inte hände, försök att %{clicking_this_link} eller återgå manuellt till appen.
registration_complete: Din registrering på %{domain} är nu slutförd!
welcome_title: Välkommen %{name}!
wrong_email_hint: Om e-postadressen inte är rätt, kan du ändra den i kontoinställningarna.
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index 8069c76c6d..85db04715b 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -1077,12 +1077,12 @@ uk:
hint_html: Ще одне! Ми повинні пересвідчитись, що ви людина (щоб ми могли уникнути спаму!). Розв'яжіть CAPTCHA внизу і натисніть кнопку "Продовжити".
title: Перевірка безпеки
confirmations:
- awaiting_review: Ваша електронна адреса підтверджена! Співробітники %{domain} тепер переглядають вашу реєстрацію. Ви отримаєте електронного листа, якщо вони затвердять ваш обліковий запис!
+ awaiting_review: Ваша електронна адреса підтверджена! Наразі співробітники %{domain} розглядають вашу реєстрацію. Ви отримаєте електронний лист, якщо вони затвердять ваш обліковий запис!
awaiting_review_title: Ваша реєстрація розглядається
clicking_this_link: натисніть це посилання
login_link: увійти
proceed_to_login_html: Тепер ви можете перейти до %{login_link}.
- redirect_to_app_html: Ви мали бути перенаправлені до програми %{app_name}. Якщо цього не сталося, спробуйте %{clicking_this_link} або вручну поверніться до програми.
+ redirect_to_app_html: Вас мало переспрямувати до програми %{app_name}. Якщо цього не сталося, спробуйте %{clicking_this_link} або вручну поверніться до програми.
registration_complete: Ваша реєстрація на %{domain} завершена!
welcome_title: Ласкаво просимо, %{name}!
wrong_email_hint: Якщо ця адреса електронної пошти неправильна, можна змінити її в налаштуваннях облікового запису.
diff --git a/config/locales/vi.yml b/config/locales/vi.yml
index 79ec13571d..ec8f6c1395 100644
--- a/config/locales/vi.yml
+++ b/config/locales/vi.yml
@@ -1023,6 +1023,14 @@ vi:
hint_html: Còn một xíu nữa! Chúng tôi cần xác minh bạn là con người (để chúng tôi có thể ngăn chặn thư rác!). Nhập CAPTCHA bên dưới và nhấn "Tiếp tục".
title: Kiểm tra an toàn
confirmations:
+ awaiting_review: Đã xác minh email của bạn! Kiểm duyệt viên %{domain} đang xem xét đăng ký của bạn. Bạn sẽ nhận được một email nếu tài khoản của bạn được duyệt!
+ awaiting_review_title: Đăng ký của bạn đang chờ duyệt
+ clicking_this_link: nhấn vào link này
+ login_link: đăng nhập
+ proceed_to_login_html: Bạn có thể tiếp tục %{login_link}.
+ redirect_to_app_html: Bạn đã có thể chuyển tiếp tới %{app_name}. Nếu không có gì xảy ra, thử %{clicking_this_link} hoặc tự quay lại app.
+ registration_complete: Hoàn tất đăng ký trên %{domain}!
+ welcome_title: Chào mừng, %{name}!
wrong_email_hint: Nếu địa chỉ email đó không chính xác, bạn có thể thay đổi nó trong cài đặt tài khoản.
delete_account: Xóa tài khoản
delete_account_html: Nếu bạn muốn xóa tài khoản của mình, hãy yêu cầu tại đây. Bạn sẽ được yêu cầu xác nhận.
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index 9d75f50a50..7bcc133964 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -1027,7 +1027,7 @@ zh-TW:
confirmations:
awaiting_review: 已驗證您的電子郵件!%{domain} 的管理員正在審核您的註冊申請。若您的帳號通過審核,您將收到電子郵件通知。
awaiting_review_title: 我們正在審核您的註冊申請
- clicking_this_link: 點擊這個連結
+ clicking_this_link: 點擊此連結
login_link: 登入
proceed_to_login_html: 您現在可以前往 %{login_link}。
redirect_to_app_html: 您應被重新導向至 %{app_name} 應用程式。如尚未重新導向,請嘗試 %{clicking_this_link} 或手動回到應用程式。
diff --git a/config/webpack/rules/index.js b/config/webpack/rules/index.js
index b026857887..4be59f1b64 100644
--- a/config/webpack/rules/index.js
+++ b/config/webpack/rules/index.js
@@ -2,7 +2,6 @@ const babel = require('./babel');
const css = require('./css');
const file = require('./file');
const materialIcons = require('./material_icons');
-const nodeModules = require('./node_modules');
const tesseract = require('./tesseract');
// Webpack loaders are processed in reverse order
@@ -13,6 +12,5 @@ module.exports = {
file,
tesseract,
css,
- nodeModules,
babel,
};
diff --git a/config/webpack/rules/node_modules.js b/config/webpack/rules/node_modules.js
deleted file mode 100644
index 89c9d422d3..0000000000
--- a/config/webpack/rules/node_modules.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const { join } = require('path');
-
-const { settings, env } = require('../configuration');
-
-module.exports = {
- test: /\.(js|mjs)$/,
- include: /node_modules/,
- exclude: [
- /@babel(?:\/|\\{1,2})runtime/,
- /tesseract.js/,
- ],
- use: [
- {
- loader: 'babel-loader',
- options: {
- babelrc: false,
- plugins: [
- 'transform-react-remove-prop-types',
- ],
- cacheDirectory: join(settings.cache_path, 'babel-loader-node-modules'),
- cacheCompression: env.NODE_ENV === 'production',
- compact: false,
- sourceMaps: false,
- },
- },
- ],
-};
diff --git a/config/webpack/tests.js b/config/webpack/tests.js
deleted file mode 100644
index e6a8f1c2a9..0000000000
--- a/config/webpack/tests.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Note: You must restart bin/webpack-dev-server for changes to take effect
-
-const { merge } = require('webpack-merge');
-
-const sharedConfig = require('./shared');
-
-module.exports = merge(sharedConfig, {
- mode: 'production',
-});
diff --git a/package.json b/package.json
index 8e8117aa6e..ecf8847c2b 100644
--- a/package.json
+++ b/package.json
@@ -49,10 +49,8 @@
"@reduxjs/toolkit": "^1.9.5",
"@renchap/compression-webpack-plugin": "^6.1.4",
"@svgr/webpack": "^5.5.0",
- "abortcontroller-polyfill": "^1.7.5",
- "array-includes": "^3.1.6",
- "arrow-key-navigation": "^1.2.0",
"atrament": "0.2.4",
+ "arrow-key-navigation": "^1.2.0",
"async-mutex": "^0.4.0",
"autoprefixer": "^10.4.14",
"axios": "^1.4.0",
diff --git a/spec/controllers/admin/accounts_controller_spec.rb b/spec/controllers/admin/accounts_controller_spec.rb
index 782e460a42..b57ec67141 100644
--- a/spec/controllers/admin/accounts_controller_spec.rb
+++ b/spec/controllers/admin/accounts_controller_spec.rb
@@ -285,7 +285,10 @@ RSpec.describe Admin::AccountsController do
let(:current_user) { Fabricate(:user, role: role) }
let(:account) { Fabricate(:account, suspended: true) }
- let!(:email_block) { Fabricate(:canonical_email_block, reference_account: account) }
+
+ before do
+ _email_block = Fabricate(:canonical_email_block, reference_account: account)
+ end
context 'when user is admin' do
let(:role) { UserRole.find_by(name: 'Admin') }
diff --git a/spec/controllers/admin/action_logs_controller_spec.rb b/spec/controllers/admin/action_logs_controller_spec.rb
index 044ddf2c42..b7854469dd 100644
--- a/spec/controllers/admin/action_logs_controller_spec.rb
+++ b/spec/controllers/admin/action_logs_controller_spec.rb
@@ -8,8 +8,8 @@ describe Admin::ActionLogsController do
# Action logs typically cause issues when their targets are not in the database
let!(:account) { Fabricate(:account) }
- let!(:orphaned_logs) do
- %w(
+ before do
+ _orphaned_logs = %w(
Account User UserRole Report DomainBlock DomainAllow
EmailDomainBlock UnavailableDomain Status AccountWarning
Announcement IpBlock Instance CustomEmoji CanonicalEmailBlock Appeal
diff --git a/spec/controllers/admin/instances_controller_spec.rb b/spec/controllers/admin/instances_controller_spec.rb
index 5fed5d98d2..74d69d1aaa 100644
--- a/spec/controllers/admin/instances_controller_spec.rb
+++ b/spec/controllers/admin/instances_controller_spec.rb
@@ -8,10 +8,10 @@ RSpec.describe Admin::InstancesController do
let(:current_user) { Fabricate(:user, role: UserRole.find_by(name: 'Admin')) }
let!(:account_popular_main) { Fabricate(:account, domain: 'popular') }
- let!(:account_popular_other) { Fabricate(:account, domain: 'popular') }
- let!(:account_less_popular) { Fabricate(:account, domain: 'less.popular') }
before do
+ _account_less_popular = Fabricate(:account, domain: 'less.popular')
+ _account_popular_other = Fabricate(:account, domain: 'popular')
sign_in current_user, scope: :user
end
diff --git a/spec/controllers/admin/reports/actions_controller_spec.rb b/spec/controllers/admin/reports/actions_controller_spec.rb
index 1f3951516d..06d4b31f54 100644
--- a/spec/controllers/admin/reports/actions_controller_spec.rb
+++ b/spec/controllers/admin/reports/actions_controller_spec.rb
@@ -54,13 +54,16 @@ describe Admin::Reports::ActionsController do
describe 'POST #create' do
let(:target_account) { Fabricate(:account) }
let(:statuses) { [Fabricate(:status, account: target_account), Fabricate(:status, account: target_account)] }
- let!(:media) { Fabricate(:media_attachment, account: target_account, status: statuses[0]) }
let(:report) { Fabricate(:report, target_account: target_account, status_ids: statuses.map(&:id)) }
let(:text) { 'hello' }
let(:common_params) do
{ report_id: report.id, text: text }
end
+ before do
+ _media = Fabricate(:media_attachment, account: target_account, status: statuses[0])
+ end
+
shared_examples 'common behavior' do
it 'closes the report and redirects' do
expect { subject }.to mark_report_action_taken.and create_target_account_strike
@@ -122,14 +125,17 @@ describe Admin::Reports::ActionsController do
let(:action) { 'mark_as_sensitive' }
let(:statuses) { [media_attached_status, media_attached_deleted_status] }
- let!(:status) { Fabricate(:status, account: target_account) }
let(:media_attached_status) { Fabricate(:status, account: target_account) }
- let!(:media_attachment) { Fabricate(:media_attachment, account: target_account, status: media_attached_status) }
let(:media_attached_deleted_status) { Fabricate(:status, account: target_account, deleted_at: 1.day.ago) }
- let!(:media_attachment2) { Fabricate(:media_attachment, account: target_account, status: media_attached_deleted_status) }
let(:last_media_attached_status) { Fabricate(:status, account: target_account) }
- let!(:last_media_attachment) { Fabricate(:media_attachment, account: target_account, status: last_media_attached_status) }
- let!(:last_status) { Fabricate(:status, account: target_account) }
+
+ before do
+ _last_media_attachment = Fabricate(:media_attachment, account: target_account, status: last_media_attached_status)
+ _last_status = Fabricate(:status, account: target_account)
+ _media_attachment = Fabricate(:media_attachment, account: target_account, status: media_attached_status)
+ _media_attachment2 = Fabricate(:media_attachment, account: target_account, status: media_attached_deleted_status)
+ _status = Fabricate(:status, account: target_account)
+ end
it_behaves_like 'common behavior'
diff --git a/spec/controllers/admin/statuses_controller_spec.rb b/spec/controllers/admin/statuses_controller_spec.rb
index 9befdf978f..dc5e28e972 100644
--- a/spec/controllers/admin/statuses_controller_spec.rb
+++ b/spec/controllers/admin/statuses_controller_spec.rb
@@ -9,13 +9,14 @@ describe Admin::StatusesController do
let(:account) { Fabricate(:account) }
let!(:status) { Fabricate(:status, account: account) }
let(:media_attached_status) { Fabricate(:status, account: account, sensitive: !sensitive) }
- let!(:media_attachment) { Fabricate(:media_attachment, account: account, status: media_attached_status) }
let(:last_media_attached_status) { Fabricate(:status, account: account, sensitive: !sensitive) }
- let!(:last_media_attachment) { Fabricate(:media_attachment, account: account, status: last_media_attached_status) }
- let!(:last_status) { Fabricate(:status, account: account) }
let(:sensitive) { true }
before do
+ _last_media_attachment = Fabricate(:media_attachment, account: account, status: last_media_attached_status)
+ _last_status = Fabricate(:status, account: account)
+ _media_attachment = Fabricate(:media_attachment, account: account, status: media_attached_status)
+
sign_in user, scope: :user
end
diff --git a/spec/features/admin/domain_blocks_spec.rb b/spec/features/admin/domain_blocks_spec.rb
index 0d7b90c21c..4379ac91db 100644
--- a/spec/features/admin/domain_blocks_spec.rb
+++ b/spec/features/admin/domain_blocks_spec.rb
@@ -4,6 +4,7 @@ require 'rails_helper'
describe 'blocking domains through the moderation interface' do
before do
+ allow(DomainBlockWorker).to receive(:perform_async).and_return(true)
sign_in Fabricate(:user, role: UserRole.find_by(name: 'Admin')), scope: :user
end
@@ -16,6 +17,7 @@ describe 'blocking domains through the moderation interface' do
click_button I18n.t('admin.domain_blocks.new.create')
expect(DomainBlock.exists?(domain: 'example.com', severity: 'silence')).to be true
+ expect(DomainBlockWorker).to have_received(:perform_async)
end
end
@@ -27,13 +29,15 @@ describe 'blocking domains through the moderation interface' do
select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity'
click_button I18n.t('admin.domain_blocks.new.create')
- # It presents a confirmation screen
+ # It doesn't immediately block but presents a confirmation screen
expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com'))
+ expect(DomainBlockWorker).to_not have_received(:perform_async)
# Confirming creates a block
click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm')
expect(DomainBlock.exists?(domain: 'example.com', severity: 'suspend')).to be true
+ expect(DomainBlockWorker).to have_received(:perform_async)
end
end
@@ -47,13 +51,15 @@ describe 'blocking domains through the moderation interface' do
select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity'
click_button I18n.t('admin.domain_blocks.new.create')
- # It presents a confirmation screen
+ # It doesn't immediately block but presents a confirmation screen
expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com'))
+ expect(DomainBlockWorker).to_not have_received(:perform_async)
# Confirming updates the block
click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm')
expect(domain_block.reload.severity).to eq 'suspend'
+ expect(DomainBlockWorker).to have_received(:perform_async)
end
end
@@ -67,13 +73,15 @@ describe 'blocking domains through the moderation interface' do
select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity'
click_button I18n.t('admin.domain_blocks.new.create')
- # It presents a confirmation screen
+ # It doesn't immediately block but presents a confirmation screen
expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'subdomain.example.com'))
+ expect(DomainBlockWorker).to_not have_received(:perform_async)
# Confirming creates the block
click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm')
expect(DomainBlock.where(domain: 'subdomain.example.com', severity: 'suspend')).to exist
+ expect(DomainBlockWorker).to have_received(:perform_async)
# And leaves the previous block alone
expect(domain_block.reload.severity).to eq 'silence'
@@ -90,11 +98,13 @@ describe 'blocking domains through the moderation interface' do
select I18n.t('admin.domain_blocks.new.severity.suspend'), from: 'domain_block_severity'
click_button I18n.t('generic.save_changes')
- # It presents a confirmation screen
+ # It doesn't immediately block but presents a confirmation screen
expect(page).to have_title(I18n.t('admin.domain_blocks.confirm_suspension.title', domain: 'example.com'))
+ expect(DomainBlockWorker).to_not have_received(:perform_async)
# Confirming updates the block
click_button I18n.t('admin.domain_blocks.confirm_suspension.confirm')
+ expect(DomainBlockWorker).to have_received(:perform_async)
expect(domain_block.reload.severity).to eq 'suspend'
end
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index d7c4c131a2..5e92cb1d39 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -23,6 +23,109 @@ RSpec.describe ActivityPub::Activity::Create do
stub_request(:get, 'http://example.com/emojib.png').to_return(body: attachment_fixture('emojo.png'), headers: { 'Content-Type' => 'application/octet-stream' })
end
+ describe 'processing posts received out of order' do
+ let(:follower) { Fabricate(:account, username: 'bob') }
+
+ let(:object_json) do
+ {
+ id: [ActivityPub::TagManager.instance.uri_for(sender), 'post1'].join('/'),
+ type: 'Note',
+ to: [
+ 'https://www.w3.org/ns/activitystreams#Public',
+ ActivityPub::TagManager.instance.uri_for(follower),
+ ],
+ content: '@bob lorem ipsum',
+ published: 1.hour.ago.utc.iso8601,
+ updated: 1.hour.ago.utc.iso8601,
+ tag: {
+ type: 'Mention',
+ href: ActivityPub::TagManager.instance.uri_for(follower),
+ },
+ }
+ end
+
+ let(:reply_json) do
+ {
+ id: [ActivityPub::TagManager.instance.uri_for(sender), 'reply'].join('/'),
+ type: 'Note',
+ inReplyTo: object_json[:id],
+ to: [
+ 'https://www.w3.org/ns/activitystreams#Public',
+ ActivityPub::TagManager.instance.uri_for(follower),
+ ],
+ content: '@bob lorem ipsum',
+ published: Time.now.utc.iso8601,
+ updated: Time.now.utc.iso8601,
+ tag: {
+ type: 'Mention',
+ href: ActivityPub::TagManager.instance.uri_for(follower),
+ },
+ }
+ end
+
+ def activity_for_object(json)
+ {
+ '@context': 'https://www.w3.org/ns/activitystreams',
+ id: [json[:id], 'activity'].join('/'),
+ type: 'Create',
+ actor: ActivityPub::TagManager.instance.uri_for(sender),
+ object: json,
+ }.with_indifferent_access
+ end
+
+ before do
+ follower.follow!(sender)
+ end
+
+ around do |example|
+ Sidekiq::Testing.fake! do
+ example.run
+ Sidekiq::Worker.clear_all
+ end
+ end
+
+ it 'correctly processes posts and inserts them in timelines', :aggregate_failures do
+ # Simulate a temporary failure preventing from fetching the parent post
+ stub_request(:get, object_json[:id]).to_return(status: 500)
+
+ # When receiving the reply…
+ described_class.new(activity_for_object(reply_json), sender, delivery: true).perform
+
+ # NOTE: Refering explicitly to the workers is a bit awkward
+ DistributionWorker.drain
+ FeedInsertWorker.drain
+
+ # …it creates a status with an unknown parent
+ reply = Status.find_by(uri: reply_json[:id])
+ expect(reply.reply?).to be true
+ expect(reply.in_reply_to_id).to be_nil
+
+ # …and creates a notification
+ expect(LocalNotificationWorker.jobs.size).to eq 1
+
+ # …but does not insert it into timelines
+ expect(redis.zscore(FeedManager.instance.key(:home, follower.id), reply.id)).to be_nil
+
+ # When receiving the parent…
+ described_class.new(activity_for_object(object_json), sender, delivery: true).perform
+
+ Sidekiq::Worker.drain_all
+
+ # …it creates a status and insert it into timelines
+ parent = Status.find_by(uri: object_json[:id])
+ expect(parent.reply?).to be false
+ expect(parent.in_reply_to_id).to be_nil
+ expect(reply.reload.in_reply_to_id).to eq parent.id
+
+ # Check that the both statuses have been inserted into the home feed
+ expect(redis.zscore(FeedManager.instance.key(:home, follower.id), parent.id)).to be_within(0.1).of(parent.id.to_f)
+ expect(redis.zscore(FeedManager.instance.key(:home, follower.id), reply.id)).to be_within(0.1).of(reply.id.to_f)
+
+ # Creates two notifications
+ expect(Notification.count).to eq 2
+ end
+ end
+
describe '#perform' do
context 'when fetching' do
subject { described_class.new(json, sender) }
@@ -31,6 +134,46 @@ RSpec.describe ActivityPub::Activity::Create do
subject.perform
end
+ context 'when object publication date is below ISO8601 range' do
+ let(:object_json) do
+ {
+ id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+ type: 'Note',
+ content: 'Lorem ipsum',
+ published: '-0977-11-03T08:31:22Z',
+ }
+ end
+
+ it 'creates status with a valid creation date', :aggregate_failures do
+ status = sender.statuses.first
+
+ expect(status).to_not be_nil
+ expect(status.text).to eq 'Lorem ipsum'
+
+ expect(status.created_at).to be_within(30).of(Time.now.utc)
+ end
+ end
+
+ context 'when object publication date is above ISO8601 range' do
+ let(:object_json) do
+ {
+ id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+ type: 'Note',
+ content: 'Lorem ipsum',
+ published: '10000-11-03T08:31:22Z',
+ }
+ end
+
+ it 'creates status with a valid creation date', :aggregate_failures do
+ status = sender.statuses.first
+
+ expect(status).to_not be_nil
+ expect(status.text).to eq 'Lorem ipsum'
+
+ expect(status.created_at).to be_within(30).of(Time.now.utc)
+ end
+ end
+
context 'when object has been edited' do
let(:object_json) do
{
@@ -42,18 +185,16 @@ RSpec.describe ActivityPub::Activity::Create do
}
end
- it 'creates status' do
+ it 'creates status with appropriate creation and edition dates', :aggregate_failures do
status = sender.statuses.first
expect(status).to_not be_nil
expect(status.text).to eq 'Lorem ipsum'
- end
- it 'marks status as edited' do
- status = sender.statuses.first
+ expect(status.created_at).to eq '2022-01-22T15:00:00Z'.to_datetime
- expect(status).to_not be_nil
expect(status.edited?).to be true
+ expect(status.edited_at).to eq '2022-01-22T16:00:00Z'.to_datetime
end
end
diff --git a/spec/lib/content_security_policy_spec.rb b/spec/lib/content_security_policy_spec.rb
new file mode 100644
index 0000000000..2e92f815ac
--- /dev/null
+++ b/spec/lib/content_security_policy_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe ContentSecurityPolicy do
+ subject { described_class.new }
+
+ around do |example|
+ original_asset_host = Rails.configuration.action_controller.asset_host
+ original_web_domain = Rails.configuration.x.web_domain
+ original_use_https = Rails.configuration.x.use_https
+ example.run
+ Rails.configuration.action_controller.asset_host = original_asset_host
+ Rails.configuration.x.web_domain = original_web_domain
+ Rails.configuration.x.use_https = original_use_https
+ end
+
+ describe '#base_host' do
+ before { Rails.configuration.x.web_domain = 'host.example' }
+
+ it 'returns the configured value for the web domain' do
+ expect(subject.base_host).to eq 'host.example'
+ end
+ end
+
+ describe '#assets_host' do
+ context 'when asset_host is not configured' do
+ before { Rails.configuration.action_controller.asset_host = nil }
+
+ context 'with a configured web domain' do
+ before { Rails.configuration.x.web_domain = 'host.example' }
+
+ context 'when use_https is enabled' do
+ before { Rails.configuration.x.use_https = true }
+
+ it 'returns value from base host with https protocol' do
+ expect(subject.assets_host).to eq 'https://host.example'
+ end
+ end
+
+ context 'when use_https is disabled' do
+ before { Rails.configuration.x.use_https = false }
+
+ it 'returns value from base host with http protocol' do
+ expect(subject.assets_host).to eq 'http://host.example'
+ end
+ end
+ end
+ end
+
+ context 'when asset_host is configured' do
+ before do
+ Rails.configuration.action_controller.asset_host = 'https://assets.host.example'
+ end
+
+ it 'returns full value from configured host' do
+ expect(subject.assets_host).to eq 'https://assets.host.example'
+ end
+ end
+ end
+
+ describe '#media_host' do
+ context 'when there is no configured CDN' do
+ it 'defaults to using the assets_host value' do
+ expect(subject.media_host).to eq(subject.assets_host)
+ end
+ end
+
+ context 'when an S3 alias host is configured' do
+ around do |example|
+ ClimateControl.modify S3_ALIAS_HOST: 'asset-host.s3-alias.example' do
+ example.run
+ end
+ end
+
+ it 'uses the s3 alias host value' do
+ expect(subject.media_host).to eq 'https://asset-host.s3-alias.example'
+ end
+ end
+
+ context 'when an S3 alias host with a trailing path is configured' do
+ around do |example|
+ ClimateControl.modify S3_ALIAS_HOST: 'asset-host.s3-alias.example/pathname' do
+ example.run
+ end
+ end
+
+ it 'uses the s3 alias host value and preserves the path' do
+ expect(subject.media_host).to eq 'https://asset-host.s3-alias.example/pathname/'
+ end
+ end
+
+ context 'when an S3 cloudfront host is configured' do
+ around do |example|
+ ClimateControl.modify S3_CLOUDFRONT_HOST: 'asset-host.s3-cloudfront.example' do
+ example.run
+ end
+ end
+
+ it 'uses the s3 cloudfront host value' do
+ expect(subject.media_host).to eq 'https://asset-host.s3-cloudfront.example'
+ end
+ end
+
+ context 'when an azure alias host is configured' do
+ around do |example|
+ ClimateControl.modify AZURE_ALIAS_HOST: 'asset-host.azure-alias.example' do
+ example.run
+ end
+ end
+
+ it 'uses the azure alias host value' do
+ expect(subject.media_host).to eq 'https://asset-host.azure-alias.example'
+ end
+ end
+
+ context 'when s3_enabled is configured' do
+ around do |example|
+ ClimateControl.modify S3_ENABLED: 'true', S3_HOSTNAME: 'asset-host.s3.example' do
+ example.run
+ end
+ end
+
+ it 'uses the s3 hostname host value' do
+ expect(subject.media_host).to eq 'https://asset-host.s3.example'
+ end
+ end
+ end
+end
diff --git a/spec/system/unlogged_spec.rb b/spec/system/unlogged_spec.rb
new file mode 100644
index 0000000000..c3ebf51d7f
--- /dev/null
+++ b/spec/system/unlogged_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'UnloggedBrowsing' do
+ subject { page }
+
+ before do
+ visit root_path
+ end
+
+ it 'loads the home page' do
+ expect(subject).to have_css('div.app-holder')
+
+ expect(subject).to have_css('div.columns-area__panels__main')
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index fb679ba4f3..d78be0ca0a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2512,9 +2512,9 @@
"@types/react" "*"
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@>=16.9.11", "@types/react@^18.0.26", "@types/react@^18.2.7":
- version "18.2.31"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.31.tgz#74ae2630e4aa9af599584157abd3b95d96fb9b40"
- integrity sha512-c2UnPv548q+5DFh03y8lEDeMfDwBn9G3dRwfkrxQMo/dOtRHUUO57k6pHvBIfH/VF4Nh+98mZ5aaSe+2echD5g==
+ version "18.2.33"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.33.tgz#055356243dc4350a9ee6c6a2c07c5cae12e38877"
+ integrity sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
@@ -2904,11 +2904,6 @@ abort-controller@^3.0.0:
dependencies:
event-target-shim "^5.0.0"
-abortcontroller-polyfill@^1.7.5:
- version "1.7.5"
- resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed"
- integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==
-
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
@@ -3415,9 +3410,9 @@ axe-core@^4.6.2:
integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
axios@^1.4.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f"
- integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102"
+ integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
@@ -4416,9 +4411,9 @@ core-js@^2.5.0:
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-js@^3.30.2:
- version "3.33.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.33.1.tgz#ef3766cfa382482d0a2c2bc5cb52c6d88805da52"
- integrity sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==
+ version "3.33.2"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.33.2.tgz#312bbf6996a3a517c04c99b9909cdd27138d1ceb"
+ integrity sha512-XeBzWI6QL3nJQiHmdzbAOiMYqjrb7hwU7A39Qhvd/POSa/t9E1AeZyEZx3fNvp/vtM8zXwhoL0FsiS0hD0pruQ==
core-util-is@~1.0.0:
version "1.0.3"
@@ -10090,9 +10085,9 @@ punycode@1.4.1, punycode@^1.2.4, punycode@^1.4.1:
integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==
punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
- integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
+ integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
pure-rand@^6.0.0:
version "6.0.2"