diff --git a/app/controllers/api/v1_alpha/collections_controller.rb b/app/controllers/api/v1_alpha/collections_controller.rb index 7c33d3bfa2..e385822c42 100644 --- a/app/controllers/api/v1_alpha/collections_controller.rb +++ b/app/controllers/api/v1_alpha/collections_controller.rb @@ -1,33 +1,65 @@ # frozen_string_literal: true class Api::V1Alpha::CollectionsController < Api::BaseController + include Authorization + rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| render json: { error: ValidationErrorFormatter.new(e).as_json }, status: 422 end before_action :check_feature_enabled - before_action -> { doorkeeper_authorize! :write, :'write:collections' }, only: [:create] + before_action -> { doorkeeper_authorize! :write, :'write:collections' }, only: [:create, :update, :destroy] - before_action :require_user!, only: [:create] + before_action :require_user!, only: [:create, :update, :destroy] + + before_action :set_collection, only: [:show, :update, :destroy] + + after_action :verify_authorized def show cache_if_unauthenticated! - @collection = Collection.find(params[:id]) + authorize @collection, :show? render json: @collection, serializer: REST::CollectionSerializer end def create - @collection = CreateCollectionService.new.call(collection_params, current_user.account) + authorize Collection, :create? + + @collection = CreateCollectionService.new.call(collection_creation_params, current_user.account) render json: @collection, serializer: REST::CollectionSerializer end + def update + authorize @collection, :update? + + @collection.update!(collection_update_params) # TODO: Create a service for this to federate changes + + render json: @collection, serializer: REST::CollectionSerializer + end + + def destroy + authorize @collection, :destroy? + + @collection.destroy + + head 200 + end + private - def collection_params - params.permit(:name, :description, :sensitive, :discoverable, :tag, account_ids: []) + def set_collection + @collection = Collection.find(params[:id]) + end + + def collection_creation_params + params.permit(:name, :description, :sensitive, :discoverable, :tag_name, account_ids: []) + end + + def collection_update_params + params.permit(:name, :description, :sensitive, :discoverable, :tag_name) end def check_feature_enabled diff --git a/app/helpers/wrapstodon_helper.rb b/app/helpers/wrapstodon_helper.rb new file mode 100644 index 0000000000..da3b0d6fad --- /dev/null +++ b/app/helpers/wrapstodon_helper.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module WrapstodonHelper + def render_wrapstodon_share_data(report) + json = ActiveModelSerializers::SerializableResource.new( + AnnualReportsPresenter.new([report]), + serializer: REST::AnnualReportsSerializer, + scope: nil, + scope_name: :current_user + ).to_json + + # rubocop:disable Rails/OutputSafety + content_tag(:script, json_escape(json).html_safe, type: 'application/json', id: 'wrapstodon-data') + # rubocop:enable Rails/OutputSafety + end +end diff --git a/app/javascript/entrypoints/wrapstodon.tsx b/app/javascript/entrypoints/wrapstodon.tsx new file mode 100644 index 0000000000..e1eebcce57 --- /dev/null +++ b/app/javascript/entrypoints/wrapstodon.tsx @@ -0,0 +1,58 @@ +import { createRoot } from 'react-dom/client'; + +import { Provider as ReduxProvider } from 'react-redux'; + +import { + importFetchedAccounts, + importFetchedStatuses, +} from '@/mastodon/actions/importer'; +import type { ApiAnnualReportResponse } from '@/mastodon/api/annual_report'; +import { Router } from '@/mastodon/components/router'; +import { WrapstodonShare } from '@/mastodon/features/annual_report/share'; +import { IntlProvider, loadLocale } from '@/mastodon/locales'; +import { loadPolyfills } from '@/mastodon/polyfills'; +import ready from '@/mastodon/ready'; +import { setReport } from '@/mastodon/reducers/slices/annual_report'; +import { store } from '@/mastodon/store'; + +function loaded() { + const mountNode = document.getElementById('wrapstodon'); + if (!mountNode) { + throw new Error('Mount node not found'); + } + const propsNode = document.getElementById('wrapstodon-data'); + if (!propsNode) { + throw new Error('Initial state prop not found'); + } + + const initialState = JSON.parse( + propsNode.textContent, + ) as ApiAnnualReportResponse; + + const report = initialState.annual_reports[0]; + if (!report) { + throw new Error('Initial state report not found'); + } + store.dispatch(importFetchedAccounts(initialState.accounts)); + store.dispatch(importFetchedStatuses(initialState.statuses)); + + store.dispatch(setReport(report)); + + const root = createRoot(mountNode); + root.render( + + + + + + + , + ); +} + +loadPolyfills() + .then(loadLocale) + .then(() => ready(loaded)) + .catch((err: unknown) => { + console.error(err); + }); diff --git a/app/javascript/mastodon/components/logo.tsx b/app/javascript/mastodon/components/logo.tsx index fe9680d0e3..c0ed4d78a7 100644 --- a/app/javascript/mastodon/components/logo.tsx +++ b/app/javascript/mastodon/components/logo.tsx @@ -1,3 +1,5 @@ +import classNames from 'classnames'; + import logo from '@/images/logo.svg'; export const WordmarkLogo: React.FC = () => ( @@ -7,8 +9,12 @@ export const WordmarkLogo: React.FC = () => ( ); -export const IconLogo: React.FC = () => ( - +export const IconLogo: React.FC<{ className?: string }> = ({ className }) => ( + Mastodon diff --git a/app/javascript/mastodon/features/annual_report/archetype.tsx b/app/javascript/mastodon/features/annual_report/archetype.tsx index fffbc1803e..0c416c30c2 100644 --- a/app/javascript/mastodon/features/annual_report/archetype.tsx +++ b/app/javascript/mastodon/features/annual_report/archetype.tsx @@ -1,68 +1,64 @@ -import { FormattedMessage } from 'react-intl'; +import { defineMessages, useIntl } from 'react-intl'; import booster from '@/images/archetypes/booster.png'; import lurker from '@/images/archetypes/lurker.png'; import oracle from '@/images/archetypes/oracle.png'; import pollster from '@/images/archetypes/pollster.png'; import replier from '@/images/archetypes/replier.png'; -import type { Archetype as ArchetypeData } from 'mastodon/models/annual_report'; +import type { Archetype as ArchetypeData } from '@/mastodon/models/annual_report'; + +export const archetypeNames = defineMessages({ + booster: { + id: 'annual_report.summary.archetype.booster', + defaultMessage: 'The cool-hunter', + }, + replier: { + id: 'annual_report.summary.archetype.replier', + defaultMessage: 'The social butterfly', + }, + pollster: { + id: 'annual_report.summary.archetype.pollster', + defaultMessage: 'The pollster', + }, + lurker: { + id: 'annual_report.summary.archetype.lurker', + defaultMessage: 'The lurker', + }, + oracle: { + id: 'annual_report.summary.archetype.oracle', + defaultMessage: 'The oracle', + }, +}); export const Archetype: React.FC<{ data: ArchetypeData; }> = ({ data }) => { - let illustration, label; + const intl = useIntl(); + let illustration; switch (data) { case 'booster': illustration = booster; - label = ( - - ); break; case 'replier': illustration = replier; - label = ( - - ); break; case 'pollster': illustration = pollster; - label = ( - - ); break; case 'lurker': illustration = lurker; - label = ( - - ); break; case 'oracle': illustration = oracle; - label = ( - - ); break; } return ( - {label} + + {intl.formatMessage(archetypeNames[data])} + ); diff --git a/app/javascript/mastodon/features/annual_report/index.tsx b/app/javascript/mastodon/features/annual_report/index.tsx index 9c2c9d71c0..e9f0b5f2d7 100644 --- a/app/javascript/mastodon/features/annual_report/index.tsx +++ b/app/javascript/mastodon/features/annual_report/index.tsx @@ -1,68 +1,38 @@ -import { useState, useEffect } from 'react'; +import { useCallback } from 'react'; +import type { FC } from 'react'; -import { FormattedMessage } from 'react-intl'; +import { defineMessage, FormattedMessage, useIntl } from 'react-intl'; -import { - importFetchedStatuses, - importFetchedAccounts, -} from 'mastodon/actions/importer'; -import { apiRequestGet, apiRequestPost } from 'mastodon/api'; -import { LoadingIndicator } from 'mastodon/components/loading_indicator'; -import { me } from 'mastodon/initial_state'; -import type { Account } from 'mastodon/models/account'; -import type { AnnualReport as AnnualReportData } from 'mastodon/models/annual_report'; -import type { Status } from 'mastodon/models/status'; -import { useAppSelector, useAppDispatch } from 'mastodon/store'; +import { focusCompose, resetCompose } from '@/mastodon/actions/compose'; +import { closeModal } from '@/mastodon/actions/modal'; +import { Button } from '@/mastodon/components/button'; +import { LoadingIndicator } from '@/mastodon/components/loading_indicator'; +import { me } from '@/mastodon/initial_state'; +import type { AnnualReport as AnnualReportData } from '@/mastodon/models/annual_report'; +import { useAppDispatch, useAppSelector } from '@/mastodon/store'; -import { Archetype } from './archetype'; +import { Archetype, archetypeNames } from './archetype'; import { Followers } from './followers'; import { HighlightedPost } from './highlighted_post'; import { MostUsedHashtag } from './most_used_hashtag'; import { NewPosts } from './new_posts'; -import { Percentile } from './percentile'; -interface AnnualReportResponse { - annual_reports: AnnualReportData[]; - accounts: Account[]; - statuses: Status[]; -} +const shareMessage = defineMessage({ + id: 'annual_report.summary.share_message', + defaultMessage: 'I got the {archetype} archetype!', +}); -export const AnnualReport: React.FC<{ - year: string; -}> = ({ year }) => { - const [response, setResponse] = useState(null); - const [loading, setLoading] = useState(true); +// Share = false when using the embedded version of the report. +export const AnnualReport: FC<{ share?: boolean }> = ({ share = true }) => { const currentAccount = useAppSelector((state) => me ? state.accounts.get(me) : undefined, ); - const dispatch = useAppDispatch(); + const report = useAppSelector((state) => state.annualReport.report); - useEffect(() => { - apiRequestGet(`v1/annual_reports/${year}`) - .then((data) => { - dispatch(importFetchedStatuses(data.statuses)); - dispatch(importFetchedAccounts(data.accounts)); - - setResponse(data); - setLoading(false); - - return apiRequestPost(`v1/annual_reports/${year}/read`); - }) - .catch(() => { - setLoading(false); - }); - }, [dispatch, year, setResponse, setLoading]); - - if (loading) { + if (!report) { return ; } - const report = response?.annual_reports[0]; - - if (!report || report.schema_version !== 1) { - return null; - } - return ( @@ -89,9 +59,37 @@ export const AnnualReport: React.FC<{ total={currentAccount?.followers_count} /> - + {share && } ); }; + +const ShareButton: FC<{ report: AnnualReportData }> = ({ report }) => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + const handleShareClick = useCallback(() => { + // Generate the share message. + const archetypeName = intl.formatMessage( + archetypeNames[report.data.archetype], + ); + const shareLines = [ + intl.formatMessage(shareMessage, { + archetype: archetypeName, + }), + ]; + // Share URL is only available for schema version 2. + if (report.schema_version === 2 && report.share_url) { + shareLines.push(report.share_url); + } + shareLines.push(`#Wrapstodon${report.year}`); + + // Reset the composer and focus it with the share message, then close the modal. + dispatch(resetCompose()); + dispatch(focusCompose(shareLines.join('\n\n'))); + dispatch(closeModal({ modalType: 'ANNUAL_REPORT', ignoreFocus: false })); + }, [report, intl, dispatch]); + + return ; +}; diff --git a/app/javascript/mastodon/features/annual_report/share.module.css b/app/javascript/mastodon/features/annual_report/share.module.css new file mode 100644 index 0000000000..e4d01ff3e3 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/share.module.css @@ -0,0 +1,19 @@ +.wrapper { + max-width: 40rem; + margin: 0 auto; +} + +.footer { + text-align: center; + margin-top: 1rem; + display: flex; + flex-direction: column; + gap: 0.75rem; + align-items: center; + color: var(--color-text-secondary); +} + +.logo { + width: 2rem; + opacity: 0.6; +} diff --git a/app/javascript/mastodon/features/annual_report/share.tsx b/app/javascript/mastodon/features/annual_report/share.tsx new file mode 100644 index 0000000000..25b3ee9885 --- /dev/null +++ b/app/javascript/mastodon/features/annual_report/share.tsx @@ -0,0 +1,18 @@ +import type { FC } from 'react'; + +import { IconLogo } from '@/mastodon/components/logo'; + +import { AnnualReport } from './index'; +import classes from './share.module.css'; + +export const WrapstodonShare: FC = () => { + return ( + + + + + ); +}; diff --git a/app/javascript/mastodon/features/annual_report/timeline.tsx b/app/javascript/mastodon/features/annual_report/timeline.tsx index 512a192f05..ee46d20403 100644 --- a/app/javascript/mastodon/features/annual_report/timeline.tsx +++ b/app/javascript/mastodon/features/annual_report/timeline.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react'; import type { FC } from 'react'; -import { showAlert } from '@/mastodon/actions/alerts'; +import { openModal } from '@/mastodon/actions/modal'; import { generateReport, selectWrapstodonYear, @@ -20,12 +20,7 @@ export const AnnualReportTimeline: FC = () => { }, [dispatch]); const handleOpen = useCallback(() => { - dispatch( - // TODO: Implement opening the annual report view when components are ready. - showAlert({ - message: 'Not yet implemented.', - }), - ); + dispatch(openModal({ modalType: 'ANNUAL_REPORT', modalProps: {} })); }, [dispatch]); if (!year || !state || state === 'ineligible') { diff --git a/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx b/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx index 8c39c0b3aa..3a0ea987c6 100644 --- a/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx +++ b/app/javascript/mastodon/features/ui/components/annual_report_modal.tsx @@ -3,16 +3,15 @@ import { useEffect } from 'react'; import { AnnualReport } from 'mastodon/features/annual_report'; const AnnualReportModal: React.FC<{ - year: string; - onChangeBackgroundColor: (arg0: string) => void; -}> = ({ year, onChangeBackgroundColor }) => { + onChangeBackgroundColor: (color: string) => void; +}> = ({ onChangeBackgroundColor }) => { useEffect(() => { onChangeBackgroundColor('var(--indigo-1)'); }, [onChangeBackgroundColor]); return ( - + ); }; diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index 9da64c8968..5c64f8e0fc 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Апішыце гэта людзям з праблемамі са зрокам…", "alt_text_modal.done": "Гатова", "announcement.announcement": "Аб'ява", + "annual_report.announcement.action_build": "Старыць мне Вынікадон", + "annual_report.announcement.action_view": "Паглядзець мой Вынікадон", + "annual_report.announcement.description": "Даведайцеся больш пра Вашыя ўзаемадзеянні ў Mastodon за апошні год.", + "annual_report.announcement.title": "Вынікадон {year} ужо тут", "annual_report.summary.archetype.booster": "Паляўнічы на трэнды", "annual_report.summary.archetype.lurker": "Назіральнік", "annual_report.summary.archetype.oracle": "Аракул", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index 81f89f962c..d546426cf2 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Descriviu això per a persones amb problemes visuals…", "alt_text_modal.done": "Fet", "announcement.announcement": "Anunci", + "annual_report.announcement.action_build": "El meu Wrapstodon s'ha fet", + "annual_report.announcement.action_view": "Vegeu el meu Wrapstodon", + "annual_report.announcement.description": "Descobriu més sobre el vostre involucrament a Mastodon durant l'any passat.", + "annual_report.announcement.title": "Ha arribat Wrapstodon {year}", "annual_report.summary.archetype.booster": "Sempre a la moda", "annual_report.summary.archetype.lurker": "Tot ho llegeix", "annual_report.summary.archetype.oracle": "L'Oracle", @@ -131,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "publicacions noves", "annual_report.summary.percentile.text": "Que us posa alcapdamunt dels usuaris de {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "No li ho direm al Bernie.", + "annual_report.summary.share_message": "Tinc l'arquetip {archetype}!", "annual_report.summary.thanks": "Gràcies per formar part de Mastodon!", "attachments_list.unprocessed": "(sense processar)", "audio.hide": "Amaga l'àudio", @@ -514,6 +519,7 @@ "keyboard_shortcuts.toggle_hidden": "Mostra/amaga el text marcat com a sensible", "keyboard_shortcuts.toggle_sensitivity": "Mostra/amaga contingut", "keyboard_shortcuts.toot": "Escriu un nou tut", + "keyboard_shortcuts.top": "Mou al capdamunt de la llista", "keyboard_shortcuts.translate": "per a traduir una publicació", "keyboard_shortcuts.unfocus": "Descentra l'àrea de composició de text/cerca", "keyboard_shortcuts.up": "Apuja a la llista", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 3d36763958..eca4a8b6eb 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -121,7 +121,7 @@ "annual_report.summary.archetype.lurker": "Lureren", "annual_report.summary.archetype.oracle": "Oraklet", "annual_report.summary.archetype.pollster": "Afstemningsmageren", - "annual_report.summary.archetype.replier": "Den social sommerfugl", + "annual_report.summary.archetype.replier": "Den sociale sommerfugl", "annual_report.summary.followers.followers": "følgere", "annual_report.summary.followers.total": "{count} i alt", "annual_report.summary.here_it_is": "Her er dit {year} i sammendrag:", @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nye indlæg", "annual_report.summary.percentile.text": "Dermed er du i topaf {domain}-brugere.", "annual_report.summary.percentile.we_wont_tell_bernie": "Vi fortæller det ikke til nogen.", + "annual_report.summary.share_message": "Min arketype er {archetype}!", "annual_report.summary.thanks": "Tak for at være en del af Mastodon!", "attachments_list.unprocessed": "(ubehandlet)", "audio.hide": "Skjul lyd", @@ -613,7 +614,7 @@ "notification.admin.report_statuses_other": "{name} anmeldte {target}", "notification.admin.sign_up": "{name} tilmeldte sig", "notification.admin.sign_up.name_and_others": "{name} og {count, plural, one {# anden} other {# andre}} tilmeldte sig", - "notification.annual_report.message": "{year} #Wrapstodon venter! Afslør årets højdepunkter og mindeværdige øjeblikke på Mastodon!", + "notification.annual_report.message": "Din {year} #Wrapstodon venter! Afslør årets højdepunkter og mindeværdige øjeblikke på Mastodon!", "notification.annual_report.view": "Vis #Wrapstodon", "notification.favourite": "{name} føjede dit indlæg til favoritter", "notification.favourite.name_and_others_with_link": "{name} og {count, plural, one {# anden} other {# andre}} føjede dit indlæg til favoritter", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index d8491118e7..73ee79e6b0 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -37,7 +37,7 @@ "account.featured": "Vorgestellt", "account.featured.accounts": "Profile", "account.featured.hashtags": "Hashtags", - "account.featured_tags.last_status_at": "Letzter Beitrag am {date}", + "account.featured_tags.last_status_at": "Neuester Beitrag vom {date}", "account.featured_tags.last_status_never": "Keine Beiträge", "account.follow": "Folgen", "account.follow_back": "Ebenfalls folgen", @@ -90,17 +90,17 @@ "account.unmute": "Stummschaltung von @{name} aufheben", "account.unmute_notifications_short": "Stummschaltung der Benachrichtigungen aufheben", "account.unmute_short": "Stummschaltung aufheben", - "account_note.placeholder": "Klicken, um Notiz hinzuzufügen", - "admin.dashboard.daily_retention": "Verweildauer der Nutzer*innen pro Tag nach der Registrierung", - "admin.dashboard.monthly_retention": "Verweildauer der Nutzer*innen pro Monat nach der Registrierung", + "account_note.placeholder": "Klicken, um private Anmerkung hinzuzufügen", + "admin.dashboard.daily_retention": "Verweildauer der Nutzer*innen pro Tag seit der Registrierung", + "admin.dashboard.monthly_retention": "Verweildauer der Nutzer*innen pro Monat seit der Registrierung", "admin.dashboard.retention.average": "Durchschnitt", "admin.dashboard.retention.cohort": "Monat der Registrierung", "admin.dashboard.retention.cohort_size": "Neue Konten", - "admin.impact_report.instance_accounts": "Profilkonten, die dadurch gelöscht würden", + "admin.impact_report.instance_accounts": "Konten, die dadurch gelöscht würden", "admin.impact_report.instance_followers": "Follower, die unsere Nutzer*innen verlieren würden", "admin.impact_report.instance_follows": "Follower, die deren Nutzer*innen verlieren würden", "admin.impact_report.title": "Zusammenfassung der Auswirkung", - "alert.rate_limited.message": "Bitte versuche es nach {retry_time, time, medium} erneut.", + "alert.rate_limited.message": "Bitte versuche es um {retry_time, time, medium} erneut.", "alert.rate_limited.title": "Anfragelimit überschritten", "alert.unexpected.message": "Ein unerwarteter Fehler ist aufgetreten.", "alert.unexpected.title": "Ups!", @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "neue Beiträge", "annual_report.summary.percentile.text": "Damit gehörst du zu den oberstender Nutzer*innen auf {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "Wir werden Bernie nichts verraten.", + "annual_report.summary.share_message": "Ich habe den {archetype} Archetyp!", "annual_report.summary.thanks": "Danke, dass du Teil von Mastodon bist!", "attachments_list.unprocessed": "(ausstehend)", "audio.hide": "Audio ausblenden", @@ -163,9 +164,9 @@ "bundle_modal_error.retry": "Erneut versuchen", "carousel.current": "Seite {current, number}/{max, number}", "carousel.slide": "Seite {current, number} von {max, number}", - "closed_registrations.other_server_instructions": "Da Mastodon dezentralisiert ist, kannst du ein Konto auf einem anderen Server erstellen und trotzdem mit diesem Server interagieren.", + "closed_registrations.other_server_instructions": "Da Mastodon dezentralisiert ist, kannst du dich auch woanders im Fediverse registrieren und trotzdem mit diesem Server in Kontakt bleiben.", "closed_registrations_modal.description": "Das Anlegen eines Kontos auf {domain} ist derzeit nicht möglich, aber bedenke, dass du nicht zwingend auf {domain} ein Konto benötigst, um Mastodon nutzen zu können.", - "closed_registrations_modal.find_another_server": "Einen anderen Server auswählen", + "closed_registrations_modal.find_another_server": "Anderen Server suchen", "closed_registrations_modal.preamble": "Mastodon ist dezentralisiert, das heißt, unabhängig davon, wo du dein Konto erstellst, kannst du jedem Profil auf diesem Server folgen und mit ihm interagieren. Du kannst sogar deinen eigenen Mastodon-Server hosten!", "closed_registrations_modal.title": "Bei Mastodon registrieren", "column.about": "Über", @@ -174,7 +175,7 @@ "column.community": "Lokale Timeline", "column.create_list": "Liste erstellen", "column.direct": "Private Erwähnungen", - "column.directory": "Profile durchsuchen", + "column.directory": "Profile durchstöbern", "column.domain_blocks": "Blockierte Domains", "column.edit_list": "Liste bearbeiten", "column.favourites": "Favoriten", @@ -288,8 +289,8 @@ "copypaste.copied": "Kopiert", "copypaste.copy_to_clipboard": "In die Zwischenablage kopieren", "directory.federated": "Aus bekanntem Fediverse", - "directory.local": "Nur von der Domain {domain}", - "directory.new_arrivals": "Neue Benutzer*innen", + "directory.local": "Nur von dieser Domain {domain}", + "directory.new_arrivals": "Neue Profile", "directory.recently_active": "Kürzlich aktiv", "disabled_account_banner.account_settings": "Kontoeinstellungen", "disabled_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert.", @@ -479,7 +480,7 @@ "interaction_modal.action": "Melde dich auf deinem Mastodon-Server an, damit du mit dem Beitrag von {name} interagieren kannst.", "interaction_modal.go": "Los", "interaction_modal.no_account_yet": "Du hast noch kein Konto?", - "interaction_modal.on_another_server": "Auf einem anderen Server", + "interaction_modal.on_another_server": "Auf anderem Server", "interaction_modal.on_this_server": "Auf diesem Server", "interaction_modal.title": "Melde dich an, um fortzufahren", "interaction_modal.username_prompt": "z. B. {example}", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 186bf33264..48aad8c926 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "νέες αναρτήσεις", "annual_report.summary.percentile.text": "Αυτό σε βάζει στο των κορυφαίων χρηστών του {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "Δεν θα το πούμε στον Bernie.", + "annual_report.summary.share_message": "Πήρα το αρχέτυπο {archetype}!", "annual_report.summary.thanks": "Ευχαριστούμε που συμμετέχεις στο Mastodon!", "attachments_list.unprocessed": "(μη επεξεργασμένο)", "audio.hide": "Απόκρυψη αρχείου ήχου", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 3a7add31c8..db9267250b 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "new posts", "annual_report.summary.percentile.text": "That puts you in the topof {domain} users.", "annual_report.summary.percentile.we_wont_tell_bernie": "We won't tell Bernie.", + "annual_report.summary.share_message": "I got the {archetype} archetype!", "annual_report.summary.thanks": "Thanks for being part of Mastodon!", "attachments_list.unprocessed": "(unprocessed)", "audio.hide": "Hide audio", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index e9fc2f6dd7..b34e4cb3a8 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nuevos mensajes", "annual_report.summary.percentile.text": "Eso te coloca en la cima delde los usuarios de {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "Queda entre nos.", + "annual_report.summary.share_message": "¡Conseguí el arquetipo {archetype}!", "annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!", "attachments_list.unprocessed": "[sin procesar]", "audio.hide": "Ocultar audio", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index a75bdee1ee..aecb13d8c4 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -113,6 +113,7 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Describe esto para personas con discapacidad visual…", "alt_text_modal.done": "Hecho", "announcement.announcement": "Anuncio", + "annual_report.announcement.action_build": "Preparar mi Wrapstodon", "annual_report.announcement.action_view": "Ver mi Wrapstodon", "annual_report.announcement.description": "Descubre más sobre tu participación en Mastodon durante el último año.", "annual_report.announcement.title": "Wrapstodon {year} ha llegado", @@ -134,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", "annual_report.summary.percentile.text": "Eso te sitúa en el topde usuarios de {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", + "annual_report.summary.share_message": "¡Obtuve el arquetipo {archetype}!", "annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!", "attachments_list.unprocessed": "(sin procesar)", "audio.hide": "Ocultar audio", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index b755a627f3..29652f84f4 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -113,6 +113,7 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Descríbelo para personas con discapacidad visual…", "alt_text_modal.done": "Hecho", "announcement.announcement": "Comunicación", + "annual_report.announcement.action_build": "Preparar mi Wrapstodon", "annual_report.announcement.action_view": "Ver mi Wrapstodon", "annual_report.announcement.description": "Descubre más sobre tu participación en Mastodon durante el último año.", "annual_report.announcement.title": "Wrapstodon {year} ha llegado", @@ -134,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nuevas publicaciones", "annual_report.summary.percentile.text": "Eso te coloca en el topde usuarios de {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "No se lo diremos a Bernie.", + "annual_report.summary.share_message": "¡Obtuve el arquetipo {archetype}!", "annual_report.summary.thanks": "¡Gracias por ser parte de Mastodon!", "attachments_list.unprocessed": "(sin procesar)", "audio.hide": "Ocultar audio", diff --git a/app/javascript/mastodon/locales/fo.json b/app/javascript/mastodon/locales/fo.json index b23bd0694d..aa87b2c2df 100644 --- a/app/javascript/mastodon/locales/fo.json +++ b/app/javascript/mastodon/locales/fo.json @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Lýs hetta fyri fólk við tey, ið hava avmarkaða sjón…", "alt_text_modal.done": "Liðugt", "announcement.announcement": "Kunngerð", + "annual_report.announcement.action_build": "Ger mítt Wrapstodon", + "annual_report.announcement.action_view": "Vís mítt Wrapstodon", + "annual_report.announcement.description": "Fá meira at vita um títt virksemi á Mastodon seinasta árið.", + "annual_report.announcement.title": "Wrapstodon {year} er komið", "annual_report.summary.archetype.booster": "Kuli jagarin", "annual_report.summary.archetype.lurker": "Lúrarin", "annual_report.summary.archetype.oracle": "Oraklið", diff --git a/app/javascript/mastodon/locales/fr-CA.json b/app/javascript/mastodon/locales/fr-CA.json index 70466504c2..6da28963d6 100644 --- a/app/javascript/mastodon/locales/fr-CA.json +++ b/app/javascript/mastodon/locales/fr-CA.json @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Décrire pour les personnes ayant des problèmes de vue…", "alt_text_modal.done": "Terminé", "announcement.announcement": "Annonce", + "annual_report.announcement.action_build": "Générer mon Wrapstodon", + "annual_report.announcement.action_view": "Voir mon Wrapstodon", + "annual_report.announcement.description": "En découvrir plus concernant votre activité sur Mastodon pour l'année écoulée.", + "annual_report.announcement.title": "Le Wrapstodon {year} est arrivé", "annual_report.summary.archetype.booster": "Le chasseur de sang-froid", "annual_report.summary.archetype.lurker": "Le faucheur", "annual_report.summary.archetype.oracle": "L’oracle", @@ -131,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nouveaux messages", "annual_report.summary.percentile.text": "Cela vous place dans le topdes utilisateurs de {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "Nous ne le dirons pas à Bernie.", + "annual_report.summary.share_message": "J’ai obtenu l’archétype {archetype} !", "annual_report.summary.thanks": "Merci de faire partie de Mastodon!", "attachments_list.unprocessed": "(non traité)", "audio.hide": "Masquer l'audio", @@ -568,7 +573,7 @@ "mute_modal.they_can_mention_and_follow": "Ils peuvent vous mentionner et vous suivre, mais vous ne les verrez pas.", "mute_modal.they_wont_know": "Ils ne sauront pas qu'ils ont été rendus silencieux.", "mute_modal.title": "Rendre cet utilisateur silencieux ?", - "mute_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.", + "mute_modal.you_wont_see_mentions": "Vous ne verrez pas les messages qui le mentionne.", "mute_modal.you_wont_see_posts": "Il peut toujours voir vos publications, mais vous ne verrez pas les siennes.", "navigation_bar.about": "À propos", "navigation_bar.account_settings": "Mot de passe et sécurité", @@ -889,7 +894,7 @@ "status.contains_quote": "Contient la citation", "status.context.loading": "Chargement de réponses supplémentaires", "status.context.loading_error": "Impossible de charger les nouvelles réponses", - "status.context.loading_success": "Nouvelles réponses ont été chargées", + "status.context.loading_success": "De nouvelles réponses ont été chargées", "status.context.more_replies_found": "Plus de réponses trouvées", "status.context.retry": "Réessayer", "status.context.show": "Montrer", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index 91fdeff324..ebe17a1133 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Décrire pour les personnes ayant des problèmes de vue…", "alt_text_modal.done": "Terminé", "announcement.announcement": "Annonce", + "annual_report.announcement.action_build": "Générer mon Wrapstodon", + "annual_report.announcement.action_view": "Voir mon Wrapstodon", + "annual_report.announcement.description": "En découvrir plus concernant votre activité sur Mastodon pour l'année écoulée.", + "annual_report.announcement.title": "Le Wrapstodon {year} est arrivé", "annual_report.summary.archetype.booster": "Le chasseur de sang-froid", "annual_report.summary.archetype.lurker": "Le faucheur", "annual_report.summary.archetype.oracle": "L’oracle", @@ -131,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nouveaux messages", "annual_report.summary.percentile.text": "Cela vous place dans le topdes utilisateurs de {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "Nous ne le dirons pas à Bernie.", + "annual_report.summary.share_message": "J’ai obtenu l’archétype {archetype} !", "annual_report.summary.thanks": "Merci de faire partie de Mastodon!", "attachments_list.unprocessed": "(non traité)", "audio.hide": "Masquer l'audio", @@ -568,7 +573,7 @@ "mute_modal.they_can_mention_and_follow": "Ils peuvent vous mentionner et vous suivre, mais vous ne les verrez pas.", "mute_modal.they_wont_know": "Ils ne sauront pas qu'ils ont été rendus silencieux.", "mute_modal.title": "Rendre cet utilisateur silencieux ?", - "mute_modal.you_wont_see_mentions": "Vous ne verrez pas les publications qui le mentionne.", + "mute_modal.you_wont_see_mentions": "Vous ne verrez pas les messages qui le mentionne.", "mute_modal.you_wont_see_posts": "Il peut toujours voir vos publications, mais vous ne verrez pas les siennes.", "navigation_bar.about": "À propos", "navigation_bar.account_settings": "Mot de passe et sécurité", @@ -813,7 +818,7 @@ "report.reasons.dislike": "Cela ne me plaît pas", "report.reasons.dislike_description": "Ce n'est pas quelque chose que vous voulez voir", "report.reasons.legal": "C'est illégal", - "report.reasons.legal_description": "Vous pensez que cela viole la loi de votre pays ou celui du serveur", + "report.reasons.legal_description": "Vous pensez que cela viole la loi de votre pays ou de celui du serveur", "report.reasons.other": "Pour une autre raison", "report.reasons.other_description": "Le problème ne correspond pas aux autres catégories", "report.reasons.spam": "C'est du spam", @@ -889,7 +894,7 @@ "status.contains_quote": "Contient la citation", "status.context.loading": "Chargement de réponses supplémentaires", "status.context.loading_error": "Impossible de charger les nouvelles réponses", - "status.context.loading_success": "Nouvelles réponses ont été chargées", + "status.context.loading_success": "De nouvelles réponses ont été chargées", "status.context.more_replies_found": "Plus de réponses trouvées", "status.context.retry": "Réessayer", "status.context.show": "Montrer", diff --git a/app/javascript/mastodon/locales/ga.json b/app/javascript/mastodon/locales/ga.json index 3f92c863e1..66d2e460ac 100644 --- a/app/javascript/mastodon/locales/ga.json +++ b/app/javascript/mastodon/locales/ga.json @@ -1,10 +1,10 @@ { - "about.blocks": "Freastalaithe faoi stiúir", + "about.blocks": "Freastalaithe modhnaithe", "about.contact": "Teagmháil:", "about.default_locale": "Réamhshocrú", "about.disclaimer": "Bogearra foinse oscailte saor in aisce is ea Mastodon, agus is le Mastodon gGmbH an trádmharc.", - "about.domain_blocks.no_reason_available": "Níl an fáth ar fáil", - "about.domain_blocks.preamble": "Go hiondúil, tugann Mastadán cead duit a bheith ag plé le húsáideoirí as freastalaí ar bith eile sa chomhchruinne agus a gcuid inneachair a fheiceáil. Seo iad na heisceachtaí a rinneadh ar an bhfreastalaí áirithe seo.", + "about.domain_blocks.no_reason_available": "Cúis nach bhfuil ar fáil", + "about.domain_blocks.preamble": "Go ginearálta, tugann Mastodon deis duit ábhar a fheiceáil ó aon fhreastalaí eile sa fediverse agus idirghníomhú leo. Seo iad na heisceachtaí atá déanta ar an bhfreastalaí seo.", "about.domain_blocks.silenced.explanation": "Go hiondúil ní fheicfidh tú próifílí ná inneachar ón bhfreastalaí seo, ach amháin má bhíonn tú á lorg nó má ghlacann tú lena leanúint d'aon ghnó.", "about.domain_blocks.silenced.title": "Teoranta", "about.domain_blocks.suspended.explanation": "Ní dhéanfar aon sonra ón fhreastalaí seo a phróiseáil, a stóráil ná a mhalartú, rud a fhágann nach féidir aon teagmháil ná aon chumarsáid a dhéanamh le húsáideoirí ón fhreastalaí seo.", @@ -15,17 +15,17 @@ "about.rules": "Rialacha an fhreastalaí", "account.account_note_header": "Nóta pearsanta", "account.add_or_remove_from_list": "Cuir Le nó Bain De na liostaí", - "account.badges.bot": "Bota", + "account.badges.bot": "Uathoibrithe", "account.badges.group": "Grúpa", - "account.block": "Déan cosc ar @{name}", + "account.block": "Bac @{name}", "account.block_domain": "Bac ainm fearainn {domain}", - "account.block_short": "Bloc", + "account.block_short": "Bac", "account.blocked": "Bactha", "account.blocking": "Ag Blocáil", - "account.cancel_follow_request": "Éirigh as iarratas leanta", + "account.cancel_follow_request": "Cealaigh leanúint", "account.copy": "Cóipeáil nasc chuig an bpróifíl", "account.direct": "Luaigh @{name} go príobháideach", - "account.disable_notifications": "Éirigh as ag cuir mé in eol nuair bpostálann @{name}", + "account.disable_notifications": "Stop ag cur in iúl dom nuair a dhéanann @{name} postáil", "account.domain_blocking": "Fearann a bhlocáil", "account.edit_profile": "Cuir an phróifíl in eagar", "account.edit_profile_short": "Cuir in Eagar", @@ -40,7 +40,7 @@ "account.featured_tags.last_status_at": "Postáil is déanaí ar {date}", "account.featured_tags.last_status_never": "Gan aon phoist", "account.follow": "Lean", - "account.follow_back": "Leanúint ar ais", + "account.follow_back": "Lean ar ais", "account.follow_back_short": "Lean ar ais", "account.follow_request": "Iarratas chun leanúint", "account.follow_request_cancel": "Cealaigh an t-iarratas", @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Déan cur síos air seo do dhaoine a bhfuil lagú amhairc orthu…", "alt_text_modal.done": "Déanta", "announcement.announcement": "Fógra", + "annual_report.announcement.action_build": "Tóg mo Wrapstodon", + "annual_report.announcement.action_view": "Féach ar mo Wrapstodon", + "annual_report.announcement.description": "Faigh tuilleadh eolais faoi do rannpháirtíocht ar Mastodon le bliain anuas.", + "annual_report.announcement.title": "Tá Wrapstodon {year} tagtha", "annual_report.summary.archetype.booster": "An sealgair fionnuar", "annual_report.summary.archetype.lurker": "An lurker", "annual_report.summary.archetype.oracle": "An oracal", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 06b6a5c8d6..7948374732 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Describe isto para as persoas con dificultades visuais…", "alt_text_modal.done": "Feito", "announcement.announcement": "Anuncio", + "annual_report.announcement.action_build": "Crear o meu Wrapstodon", + "annual_report.announcement.action_view": "Ver o meu Wrapstodon", + "annual_report.announcement.description": "Olla o que andiveches facendo en Mastodon durante o último ano.", + "annual_report.announcement.title": "Chegou o Wrapstodon de {year}", "annual_report.summary.archetype.booster": "O Telexornal", "annual_report.summary.archetype.lurker": "Volleur", "annual_report.summary.archetype.oracle": "Sabichón", @@ -516,6 +520,7 @@ "keyboard_shortcuts.toggle_hidden": "Para mostrar o texto tras Aviso de Contido (CW)", "keyboard_shortcuts.toggle_sensitivity": "Para amosar/agochar contido multimedia", "keyboard_shortcuts.toot": "Para escribir unha nova publicación", + "keyboard_shortcuts.top": "Mover arriba de todo", "keyboard_shortcuts.translate": "para traducir unha publicación", "keyboard_shortcuts.unfocus": "Para deixar de destacar a área de escritura/procura", "keyboard_shortcuts.up": "Para mover cara arriba na listaxe", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 29fe1176fc..ea0bc4b44f 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "הודעות חדשות", "annual_report.summary.percentile.text": "ממקם אותך באחוזון של משמשי {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "לא נגלה לברני.", + "annual_report.summary.share_message": "זוהיתי כדוגמא לטיפוס {archetype}!", "annual_report.summary.thanks": "תודה על היותך חלק ממסטודון!", "attachments_list.unprocessed": "(לא מעובד)", "audio.hide": "השתק", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index d1df41ed7b..c62a332a96 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -113,7 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Írd le a látássérültek számára…", "alt_text_modal.done": "Kész", "announcement.announcement": "Közlemény", - "annual_report.announcement.action_view": "A Wrapstodon-om megtekintése", + "annual_report.announcement.action_build": "Saját Wrapstodon összeállítása", + "annual_report.announcement.action_view": "Saját Wrapstodon megtekintése", + "annual_report.announcement.description": "Fedezz fel többet a Mastodonon az elmúlt évben végzett tevékenységeidről.", + "annual_report.announcement.title": "A Wrapstodon {year} megérkezett", "annual_report.summary.archetype.booster": "A cool-vadász", "annual_report.summary.archetype.lurker": "A settenkedő", "annual_report.summary.archetype.oracle": "Az orákulum", @@ -517,7 +520,7 @@ "keyboard_shortcuts.toggle_hidden": "Tartalmi figyelmeztetéssel ellátott szöveg megjelenítése/elrejtése", "keyboard_shortcuts.toggle_sensitivity": "Média megjelenítése/elrejtése", "keyboard_shortcuts.toot": "Új bejegyzés írása", - "keyboard_shortcuts.top": "Ugorj a lista elejére", + "keyboard_shortcuts.top": "Ugrás a lista elejére", "keyboard_shortcuts.translate": "Bejegyzés lefordítása", "keyboard_shortcuts.unfocus": "Szerkesztés/keresés fókuszból való kivétele", "keyboard_shortcuts.up": "Mozgás felfelé a listában", @@ -611,7 +614,7 @@ "notification.admin.sign_up": "{name} regisztrált", "notification.admin.sign_up.name_and_others": "{name} és {count, plural, one {# másik} other {# másik}} regisztrált", "notification.annual_report.message": "Vár a {year}. év #Wrapstodon jelentése! Fedd fel az éved jelentős eseményeit és emlékezetes pillanatait a Mastodonon!", - "notification.annual_report.view": "#Wrapstodon Megtekintése", + "notification.annual_report.view": "#Wrapstodon megtekintése", "notification.favourite": "{name} kedvencnek jelölte a bejegyzésedet", "notification.favourite.name_and_others_with_link": "{name} és {count, plural, one {# másik} other {# másik}} kedvencnek jelölte a bejegyzésedet", "notification.favourite_pm": "{name} kedvelte a privát említésedet", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 304ee7046b..5462f0c0ba 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nýjar færslur", "annual_report.summary.percentile.text": "Þetta setur þig á meðalof {domain} virkustu notendanna.", "annual_report.summary.percentile.we_wont_tell_bernie": "Við förum ekkert að raupa um þetta.", + "annual_report.summary.share_message": "Ég er víst {archetype}-týpan!", "annual_report.summary.thanks": "Takk fyrir að vera hluti af Mastodon-samfélaginu!", "attachments_list.unprocessed": "(óunnið)", "audio.hide": "Fela hljóð", diff --git a/app/javascript/mastodon/locales/lt.json b/app/javascript/mastodon/locales/lt.json index 09867bcf9f..3715de9091 100644 --- a/app/javascript/mastodon/locales/lt.json +++ b/app/javascript/mastodon/locales/lt.json @@ -51,7 +51,7 @@ "account.followers_counter": "{count, plural, one {{counter} sekėjas} few {{counter} sekėjai} many {{counter} sekėjo} other {{counter} sekėjų}}", "account.followers_you_know_counter": "{counter} žinomas", "account.following": "Sekama", - "account.following_counter": "{count, plural, one {{counter} sekimas} few {{counter} sekimai} many {{counter} sekimo} other {{counter} sekimų}}", + "account.following_counter": "{count, plural, one {{counter} seka} few {{counter} seka} many {{counter} seka} other {{counter} seka}}", "account.follows.empty": "Šis naudotojas dar nieko neseka.", "account.follows_you": "Seka tave", "account.go_to_profile": "Eiti į profilį", @@ -113,6 +113,10 @@ "alt_text_modal.describe_for_people_with_visual_impairments": "Aprašykite tai regos sutrikimų turintiems asmenims…", "alt_text_modal.done": "Atlikta", "announcement.announcement": "Skelbimas", + "annual_report.announcement.action_build": "Sukurti mano Wrapstodon", + "annual_report.announcement.action_view": "Peržiūrėti mano Wrapstodon", + "annual_report.announcement.description": "Sužinokite daugiau apie savo aktyvumą Mastodon\"e per pastaruosius metus.", + "annual_report.announcement.title": "Wrapstodon {year} jau čia", "annual_report.summary.archetype.booster": "Šaunus medžiotojas", "annual_report.summary.archetype.lurker": "Stebėtojas", "annual_report.summary.archetype.oracle": "Vydūnas", @@ -131,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "nauji įrašai", "annual_report.summary.percentile.text": "Tai reiškia, kad esate tarppopuliariausių {domain} naudotojų.", "annual_report.summary.percentile.we_wont_tell_bernie": "Mes nesakysime Bernie.", + "annual_report.summary.share_message": "Aš gavau {archetype}!", "annual_report.summary.thanks": "Dėkojame, kad esate „Mastodon“ dalis!", "attachments_list.unprocessed": "(neapdorotas)", "audio.hide": "Slėpti garsą", @@ -157,6 +162,7 @@ "bundle_modal_error.close": "Uždaryti", "bundle_modal_error.message": "Įkeliant šį ekraną kažkas nutiko ne taip.", "bundle_modal_error.retry": "Bandyti dar kartą", + "carousel.current": "Skirtukas {current, number} / {max, number}", "carousel.slide": "Rodoma {current, number} iš {max, number}", "closed_registrations.other_server_instructions": "Kadangi „Mastodon“ yra decentralizuotas, gali susikurti paskyrą kitame serveryje ir vis tiek bendrauti su šiuo serveriu.", "closed_registrations_modal.description": "Sukurti paskyrą serveryje {domain} šiuo metu neįmanoma, bet nepamiršk, kad norint naudotis „Mastodon“ nebūtina turėti paskyrą serveryje {domain}.", @@ -640,6 +646,8 @@ "notification.reblog": "{name} pakėlė tavo įrašą", "notification.reblog.name_and_others_with_link": "{name} ir {count, plural,one {dar kažkas} few {# kiti} other {# kitų}} paryškino tavo įrašą", "notification.relationships_severance_event": "Prarasti sąryšiai su {name}", + "notification.relationships_severance_event.account_suspension": "Administratorius iš {from} sustabdė {target}, todėl jūs nebegalėsite gauti jų naujienų ar bendrauti su jais.", + "notification.relationships_severance_event.domain_block": "Administratorius iš {from} užblokavo {target}, įskaitant {followersCount} iš tavo sekėjų ir {followingCount, plural,one {# žmogų, kurį} few {# žmones, kuriuos} other {# žmonių, kuriuos}} seki.", "notification.relationships_severance_event.learn_more": "Sužinoti daugiau", "notification.relationships_severance_event.user_domain_block": "Tu užblokavai {target}. Pašalinama {followersCount} savo sekėjų ir {followingCount, plural, one {# paskyrą} few {# paskyrai} many {# paskyros} other {# paskyrų}}, kurios seki.", "notification.status": "{name} ką tik paskelbė", @@ -710,8 +718,10 @@ "notifications.policy.filter_new_accounts.hint": "Sukurta per {days, plural, one {vieną dieną} few {# dienas} many {# dienos} other {# dienų}}", "notifications.policy.filter_new_accounts_title": "Naujos paskyros", "notifications.policy.filter_not_followers_hint": "Įskaitant žmones, kurie seka jus mažiau nei {days, plural, one {vieną dieną} few {# dienas} many {# dienų} other {# dienų}}", + "notifications.policy.filter_not_followers_title": "Žmonės, kurie neseka tavęs", "notifications.policy.filter_not_following_hint": "Kol jų nepatvirtinsi rankiniu būdu", "notifications.policy.filter_not_following_title": "Žmonių, kuriuos neseki", + "notifications.policy.filter_private_mentions_hint": "Filtruojama, išskyrus atsakymus į tavo paties paminėjimą arba jei seki siuntėją", "notifications.policy.filter_private_mentions_title": "Nepageidaujami privatūs paminėjimai", "notifications.policy.title": "Tvarkyti pranešimus iš…", "notifications_permission_banner.enable": "Įjungti darbalaukio pranešimus", @@ -756,6 +766,7 @@ "privacy.quote.disabled": "{visibility}, paminėjimai išjungti", "privacy.quote.limited": "{visibility}, paminėjimai apriboti", "privacy.unlisted.additional": "Tai veikia lygiai taip pat, kaip ir vieša, tik įrašas nebus rodomas tiesioginiuose srautuose, saitažodžiose, naršyme ar Mastodon paieškoje, net jei esi įtraukęs (-usi) visą paskyrą.", + "privacy.unlisted.long": "Paslėptas nuo „Mastodon“ paieškos rezultatų, tendencijų ir viešų įrašų sienų", "privacy.unlisted.short": "Tyliai vieša", "privacy_policy.last_updated": "Paskutinį kartą atnaujinta {date}", "privacy_policy.title": "Privatumo politika", @@ -836,6 +847,7 @@ "report_notification.categories.violation": "Taisyklės pažeidimas", "report_notification.categories.violation_sentence": "taisyklės pažeidimas", "report_notification.open": "Atidaryti ataskaitą", + "search.clear": "Išvalyti paiešką", "search.no_recent_searches": "Nėra naujausių paieškų.", "search.placeholder": "Paieška", "search.quick_action.account_search": "Profiliai, atitinkantys {x}", @@ -880,9 +892,16 @@ "status.cannot_quote": "Jums neleidžiama paminėti šio įrašo", "status.cannot_reblog": "Šis įrašas negali būti pakeltas.", "status.contains_quote": "Turi citatą", + "status.context.loading": "Įkeliama daugiau atsakymų", + "status.context.loading_error": "Nepavyko įkelti naujų atsakymų", + "status.context.loading_success": "Įkelti nauji atsakymai", + "status.context.more_replies_found": "Rasta daugiau atsakymų", + "status.context.retry": "Kartoti", + "status.context.show": "Rodyti", "status.continued_thread": "Tęsiama gijoje", "status.copy": "Kopijuoti nuorodą į įrašą", "status.delete": "Ištrinti", + "status.delete.success": "Įrašas ištrintas", "status.detailed_status": "Išsami pokalbio peržiūra", "status.direct": "Privačiai paminėti @{name}", "status.direct_indicator": "Privatus paminėjimas", @@ -957,6 +976,8 @@ "subscribed_languages.target": "Keisti prenumeruojamas kalbas {target}", "tabs_bar.home": "Pagrindinis", "tabs_bar.notifications": "Pranešimai", + "tabs_bar.publish": "Naujas įrašas", + "tabs_bar.search": "Paieška", "terms_of_service.effective_as_of": "Įsigaliojo nuo {date}.", "terms_of_service.title": "Paslaugų sąlygos", "terms_of_service.upcoming_changes_on": "Numatomi pakeitimai {date}.", diff --git a/app/javascript/mastodon/locales/pa.json b/app/javascript/mastodon/locales/pa.json index c1e3990711..5d49bfa40a 100644 --- a/app/javascript/mastodon/locales/pa.json +++ b/app/javascript/mastodon/locales/pa.json @@ -81,7 +81,7 @@ "admin.dashboard.retention.cohort_size": "ਨਵੇਂ ਵਰਤੋਂਕਾਰ", "alert.unexpected.title": "ਓਹੋ!", "alt_text_badge.title": "ਬਦਲੀ ਲਿਖਤ", - "alt_text_modal.add_alt_text": "ਬਦਲਵੀ ਲਿਖਤ ਜੋੜੋ", + "alt_text_modal.add_alt_text": "ਬਦਲਵੀ ਲਿਖਤ ਨੂੰ ਜੋੜੋ", "alt_text_modal.cancel": "ਰੱਦ ਕਰੋ", "alt_text_modal.done": "ਮੁਕੰਮਲ", "announcement.announcement": "ਹੋਕਾ", @@ -110,6 +110,7 @@ "bundle_modal_error.retry": "ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ", "carousel.current": "ਸਲਾਈਡ {current, number} / {max, number}", "carousel.slide": "{max, number} ਵਿੱਚੋਂ {current, number} ਸਲਾਈਡ", + "closed_registrations_modal.find_another_server": "ਹੋਰ ਸਰਵਰ ਲੱਭੋ", "closed_registrations_modal.title": "Mastodon ਲਈ ਸਾਈਨ ਅੱਪ ਕਰੋ", "column.about": "ਸਾਡੇ ਬਾਰੇ", "column.blocks": "ਪਾਬੰਦੀ ਲਾਏ ਵਰਤੋਂਕਾਰ", @@ -172,14 +173,20 @@ "confirmations.delete_list.confirm": "ਹਟਾਓ", "confirmations.delete_list.message": "ਕੀ ਤੁਸੀਂ ਇਸ ਸੂਚੀ ਨੂੰ ਪੱਕੇ ਤੌਰ ਉੱਤੇ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", "confirmations.delete_list.title": "ਸੂਚੀ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?", + "confirmations.discard_draft.confirm": "ਖ਼ਾਰਜ ਕਰਕੇ ਜਾਰੀ ਰੱਖੋ", + "confirmations.discard_draft.edit.cancel": "ਸੋਧਣਾ ਜਾਰੀ ਰੱਖੋ", + "confirmations.discard_draft.post.cancel": "ਖਰੜੇ ਉੱਤੇ ਕੰਮ ਜਾਰੀ ਰੱਖੋ", "confirmations.discard_edit_media.confirm": "ਰੱਦ ਕਰੋ", "confirmations.follow_to_list.confirm": "ਫ਼ਾਲੋ ਕਰੋ ਅਤੇ ਲਿਸਟ 'ਚ ਜੋੜੋ", "confirmations.follow_to_list.title": "ਵਰਤੋਂਕਾਰ ਨੂੰ ਫ਼ਾਲੋ ਕਰਨਾ ਹੈ?", "confirmations.logout.confirm": "ਬਾਹਰ ਹੋਵੋ", "confirmations.logout.message": "ਕੀ ਤੁਸੀਂ ਲਾਗ ਆਉਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", "confirmations.logout.title": "ਲਾਗ ਆਉਟ ਕਰਨਾ ਹੈ?", + "confirmations.missing_alt_text.confirm": "ਬਦਲਵੀ ਲਿਖਤ ਨੂੰ ਜੋੜੋ", "confirmations.missing_alt_text.secondary": "ਕਿਵੇਂ ਵੀ ਪੋਸਟ ਕਰੋ", + "confirmations.missing_alt_text.title": "ਬਦਲਵੀ ਲਿਖਤ ਜੋੜਨੀ ਹੈ?", "confirmations.mute.confirm": "ਮੌਨ ਕਰੋ", + "confirmations.private_quote_notify.cancel": "ਸੋਧ ਕਰਨ ਉੱਤੇ ਵਾਪਸ ਜਾਓ", "confirmations.private_quote_notify.do_not_show_again": "ਮੈਨੂੰ ਇਹ ਸੁਨੇਹਾ ਫੇਰ ਨਾ ਦਿਖਾਓ", "confirmations.quiet_post_quote_info.dismiss": "ਮੈਨੂੰ ਮੁੜ ਕੇ ਯਾਦ ਨਾ ਕਰਵਾਓ", "confirmations.quiet_post_quote_info.got_it": "ਸਮਝ ਗਏ", @@ -260,6 +267,7 @@ "filter_modal.select_filter.search": "ਖੋਜੋ ਜਾਂ ਬਣਾਓ", "filter_modal.select_filter.title": "ਇਸ ਪੋਸਟ ਨੂੰ ਫਿਲਟਰ ਕਰੋ", "filter_modal.title.status": "ਇੱਕ ਪੋਸਟ ਨੂੰ ਫਿਲਟਰ ਕਰੋ", + "filtered_notifications_banner.title": "ਫਿਲਟਰ ਕੀਤੇ ਨੋਟੀਫਿਕੇਸ਼ਨ", "firehose.all": "ਸਭ", "firehose.local": "ਇਹ ਸਰਵਰ", "firehose.remote": "ਹੋਰ ਸਰਵਰ", @@ -294,6 +302,7 @@ "hashtag.column_settings.tag_mode.none": "ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੋਈ ਨਹੀਂ", "hashtag.column_settings.tag_toggle": "Include additional tags in this column", "hashtag.follow": "ਹੈਸ਼ਟੈਗ ਨੂੰ ਫ਼ਾਲੋ ਕਰੋ", + "hashtag.mute": "#{hashtag} ਨੂੰ ਮੌਨ ਕਰੋ", "hashtag.unfollow": "ਹੈਸ਼ਟੈਗ ਨੂੰ ਅਣ-ਫ਼ਾਲੋ ਕਰੋ", "hints.profiles.see_more_followers": "{domain} ਉੱਤੇ ਹੋਰ ਫ਼ਾਲੋਅਰ ਵੇਖੋ", "hints.profiles.see_more_follows": "{domain} ਉੱਤੇ ਹੋਰ ਫ਼ਾਲੋ ਨੂੰ ਵੇਖੋ", @@ -310,6 +319,7 @@ "interaction_modal.no_account_yet": "ਹਾਲੇ ਖਾਤਾ ਨਹੀਂ ਹੈ?", "interaction_modal.on_another_server": "ਵੱਖਰੇ ਸਰਵਰ ਉੱਤੇ", "interaction_modal.on_this_server": "ਇਸ ਸਰਵਰ ਉੱਤੇ", + "interaction_modal.title": "ਜਾਰੀ ਰੱਖਣ ਲਈ ਸਾਈਨ ਇਨ ਕਰੋ", "interaction_modal.username_prompt": "ਜਿਵੇਂ {example}", "intervals.full.days": "{number, plural, one {# ਦਿਨ} other {# ਦਿਨ}}", "intervals.full.hours": "{number, plural, one {# ਘੰਟਾ} other {# ਘੰਟੇ}}", @@ -380,6 +390,7 @@ "loading_indicator.label": "ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ…", "media_gallery.hide": "ਲੁਕਾਓ", "mute_modal.hide_from_notifications": "ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਵਿੱਚੋਂ ਲੁਕਾਓ", + "mute_modal.hide_options": "ਚੋਣਾਂ ਨੂੰ ਲੁਕਾਓ", "mute_modal.show_options": "ਚੋਣਾਂ ਨੂੰ ਵੇਖਾਓ", "mute_modal.title": "ਵਰਤੋਂਕਾਰ ਨੂੰ ਮੌਨ ਕਰਨਾ ਹੈ?", "navigation_bar.about": "ਇਸ ਬਾਰੇ", @@ -397,6 +408,8 @@ "navigation_bar.followed_tags": "ਫ਼ਾਲੋ ਕੀਤੇ ਹੈਸ਼ਟੈਗ", "navigation_bar.follows_and_followers": "ਫ਼ਾਲੋ ਅਤੇ ਫ਼ਾਲੋ ਕਰਨ ਵਾਲੇ", "navigation_bar.lists": "ਸੂਚੀਆਂ", + "navigation_bar.live_feed_local": "ਲਾਈਵ ਫੀਡ (ਲੋਕਲ)", + "navigation_bar.live_feed_public": "ਲਾਈਵ ਫੀਡ (ਪਬਲਿਕ)", "navigation_bar.logout": "ਲਾਗ ਆਉਟ", "navigation_bar.more": "ਹੋਰ", "navigation_bar.mutes": "ਮੌਨ ਕੀਤੇ ਵਰਤੋਂਕਾਰ", @@ -433,16 +446,21 @@ "notification_requests.edit_selection": "ਸੋਧੋ", "notification_requests.exit_selection": "ਮੁਕੰਮਲ", "notification_requests.notifications_from": "{name} ਵਲੋਂ ਨੋਟੀਫਿਕੇਸ਼ਨ", + "notification_requests.title": "ਫਿਲਟਰ ਕੀਤੇ ਨੋਟੀਫਿਕੇਸ਼ਨ", + "notifications.clear": "ਸੂਚਨਾਵਾਂ ਨੂੰ ਮਿਟਾਓ", + "notifications.clear_confirmation": "ਕੀ ਤੁਸੀਂ ਆਪਣੇ ਸਾਰੇ ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਪੱਕੇ ਤੌਰ ਉੱਤੇ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?", "notifications.clear_title": "ਨੋਟਫਿਕੇਸ਼ਨਾਂ ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?", "notifications.column_settings.admin.report": "ਨਵੀਆਂ ਰਿਪੋਰਟਾਂ:", "notifications.column_settings.alert": "ਡੈਸਕਟਾਪ ਸੂਚਨਾਵਾਂ", "notifications.column_settings.favourite": "ਮਨਪਸੰਦ:", + "notifications.column_settings.filter_bar.advanced": "ਸਭ ਵਰਗਾਂ ਨੂੰ ਵੇਖਾਓ", "notifications.column_settings.filter_bar.category": "ਫੌਰੀ ਫਿਲਟਰ ਪੱਟੀ", "notifications.column_settings.follow": "ਨਵੇਂ ਫ਼ਾਲੋਅਰ:", "notifications.column_settings.follow_request": "ਨਵੀਆਂ ਫ਼ਾਲੋ ਬੇਨਤੀਆਂ:", "notifications.column_settings.group": "ਗਰੁੱਪ", "notifications.column_settings.mention": "ਜ਼ਿਕਰ:", "notifications.column_settings.poll": "ਪੋਲ ਦੇ ਨਤੀਜੇ:", + "notifications.column_settings.push": "ਪੁਸ਼ ਨੋਟੀਫਿਕੇਸ਼ਨ", "notifications.column_settings.quote": "ਹਵਾਲੇ:", "notifications.column_settings.reblog": "ਬੂਸਟ:", "notifications.column_settings.show": "ਕਾਲਮ ਵਿੱਚ ਵੇਖਾਓ", @@ -457,8 +475,10 @@ "notifications.filter.follows": "ਫ਼ਾਲੋ", "notifications.filter.mentions": "ਜ਼ਿਕਰ", "notifications.filter.polls": "ਪੋਲ ਦੇ ਨਤੀਜੇ", + "notifications.filter.statuses": "ਤੁਹਾਡੇ ਵਲੋਂ ਫ਼ਾਲੋ ਕੀਤੇ ਲੋਕਾਂ ਤੋਂ ਅੱਪਡੇਟ", "notifications.grant_permission": "ਇਜਾਜ਼ਤ ਦਿਓ।", "notifications.group": "{count} ਨੋਟੀਫਿਕੇਸ਼ਨ", + "notifications.mark_as_read": "ਹਰ ਨੋਟੀਫਿਕੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹੇ ਵਜੋਂ ਨਿਸ਼ਾਨੀ ਲਾਓ", "notifications.policy.accept": "ਮਨਜ਼ੂਰ", "notifications.policy.accept_hint": "ਨੋਟੀਫਿਕੇਸ਼ਨਾਂ ਵਿੱਚ ਵੇਖਾਓ", "notifications.policy.drop": "ਅਣਡਿੱਠਾ", @@ -481,6 +501,7 @@ "poll.voted": "ਤੁਸੀਂ ਇਸ ਜਵਾਬ ਲਈ ਵੋਟ ਕੀਤਾ", "privacy.change": "ਪੋਸਟ ਦੀ ਪਰਦੇਦਾਰੀ ਨੂੰ ਬਦਲੋ", "privacy.direct.long": "ਪੋਸਟ ਵਿੱਚ ਜ਼ਿਕਰ ਕੀਤੇ ਹਰ ਕੋਈ", + "privacy.direct.short": "ਨਿੱਜੀ ਜ਼ਿਕਰ", "privacy.private.long": "ਸਿਰਫ਼ ਤੁਹਾਡੇ ਫ਼ਾਲੋਅਰ ਹੀ", "privacy.private.short": "ਫ਼ਾਲੋਅਰ", "privacy.public.short": "ਜਨਤਕ", @@ -510,6 +531,7 @@ "report.category.title_account": "ਪਰੋਫਾਈਲ", "report.category.title_status": "ਪੋਸਟ", "report.close": "ਮੁਕੰਮਲ", + "report.forward": "{target} ਨੂੰ ਅੱਗੇ ਭੇਜੋ", "report.mute": "ਮੌਨ ਕਰੋ", "report.next": "ਅਗਲੀ", "report.placeholder": "ਵਧੀਕ ਟਿੱਪਣੀਆਂ", @@ -527,6 +549,7 @@ "report.unfollow": "@{name} ਨੂੰ ਅਣ-ਫ਼ਾਲੋ ਕਰੋ", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", "report_notification.categories.legal": "ਕਨੂੰਨੀ", + "report_notification.categories.legal_sentence": "ਗ਼ੈਰ-ਕਨੂੰਨੀ ਸਮੱਗਰੀ", "report_notification.categories.other": "ਬਾਕੀ", "report_notification.categories.other_sentence": "ਹੋਰ", "report_notification.categories.spam": "ਸਪੈਮ", @@ -534,6 +557,7 @@ "report_notification.categories.violation": "ਨਿਯਮ ਦੀ ਉਲੰਘਣਾ", "report_notification.categories.violation_sentence": "ਨਿਯਮ ਦੀ ਉਲੰਘਣਾ", "report_notification.open": "ਰਿਪੋਰਟ ਨੂੰ ਖੋਲ੍ਹੋ", + "search.clear": "ਖੋਜ ਨੂੰ ਸਾਫ਼ ਕਰੋ", "search.no_recent_searches": "ਕੋਈ ਸੱਜਰੀ ਖੋਜ ਨਹੀਂ ਹੈ", "search.placeholder": "ਖੋਜੋ", "search.quick_action.go_to_account": "ਪਰੋਫਾਈਲ {x} ਉੱਤੇ ਜਾਓ", @@ -550,6 +574,7 @@ "search_results.no_results": "ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ ਹਨ।", "search_results.see_all": "ਸਭ ਵੇਖੋ", "search_results.statuses": "ਪੋਸਟਾਂ", + "search_results.title": "\"{q}\" ਨੂੰ ਖੋਜੋ", "server_banner.active_users": "ਸਰਗਰਮ ਵਰਤੋਂਕਾਰ", "sign_in_banner.create_account": "ਖਾਤਾ ਬਣਾਓ", "sign_in_banner.sign_in": "ਲਾਗਇਨ", @@ -582,8 +607,10 @@ "status.pin": "ਪਰੋਫਾਈਲ ਉੱਤੇ ਟੰਗੋ", "status.quote": "ਹਵਾਲਾ", "status.quote.cancel": "ਹਵਾਲੇ ਨੂੰ ਰੱਦ ਕਰੋ", + "status.quotes_count": "{count, plural, one {{counter} ਹਵਾਲਾ} other {{counter} ਹਵਾਲੇ}}", "status.read_more": "ਹੋਰ ਪੜ੍ਹੋ", - "status.reblog": "ਵਧਾਓ", + "status.reblog": "ਬੂਸਟ", + "status.reblog_or_quote": "ਬੂਸਟ ਜਾਂ ਹਵਾਲਾ", "status.reblogged_by": "{name} ਨੇ ਬੂਸਟ ਕੀਤਾ", "status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.", "status.redraft": "ਹਟਾਓ ਤੇ ਮੁੜ-ਡਰਾਫਟ", diff --git a/app/javascript/mastodon/locales/tok.json b/app/javascript/mastodon/locales/tok.json index 1c36079c7f..7ed0b16de1 100644 --- a/app/javascript/mastodon/locales/tok.json +++ b/app/javascript/mastodon/locales/tok.json @@ -51,7 +51,7 @@ "account.followers_you_know_counter": "jan {counter} pi kute sama", "account.following": "sina kute e jan ni", "account.following_counter": "{count, plural, other {ona li kute e jan {counter}}}", - "account.follows.empty": "jan ni li kute e jan ala", + "account.follows.empty": "jan ni li kute ala e jan", "account.follows_you": "ona li kute e sina", "account.go_to_profile": "o tawa lipu jan", "account.hide_reblogs": "o lukin ala e pana toki tan @{name}", @@ -61,7 +61,7 @@ "account.link_verified_on": "{date} la mi sona e ni: jan seme li jo e lipu ni", "account.locked_info": "sina wile kute e jan ni la ona o toki e ken", "account.media": "sitelen", - "account.mention": "o mu e jan @{name}", + "account.mention": "o mu e @{name}", "account.moved_to": "jan ni la lipu sin li ni:", "account.mute": "o len e @{name}", "account.mute_notifications_short": "o kute ala e mu tan jan ni", @@ -74,20 +74,20 @@ "account.posts": "toki suli", "account.posts_with_replies": "toki ale", "account.remove_from_followers": "sijelo kute la o weka e sijelo \"{name}\".", - "account.report": "jan @{name} la o toki e ike tawa lawa", - "account.requested_follow": "jan {name} li wile kute e sina", + "account.report": "@{name} la o toki e jaki tawa lawa", + "account.requested_follow": "{name} li wile kute e sina", "account.requests_to_follow_you": "jan ni li wile kute e sina", - "account.share": "o pana e lipu jan @{name}", + "account.share": "o pana e lipu tan @{name}", "account.show_reblogs": "o lukin e pana toki tan @{name}", "account.statuses_counter": "{count, plural, other {toki {counter}}}", - "account.unblock": "o len ala e jan {name}", + "account.unblock": "o len ala e {name}", "account.unblock_domain": "o len ala e ma {domain}", - "account.unblock_domain_short": "o len ala e jan ni", + "account.unblock_domain_short": "o len ala", "account.unblock_short": "o len ala", "account.unendorse": "lipu jan la o suli ala e ni", "account.unfollow": "o kute ala", "account.unmute": "o len ala e @{name}", - "account.unmute_notifications_short": "o kute e mu tan jan ni", + "account.unmute_notifications_short": "o kute e mu", "account.unmute_short": "o len ala", "account_note.placeholder": "o luka e ni la sona pi sina taso", "admin.dashboard.daily_retention": "nanpa pi awen jan lon tenpo suno", @@ -133,7 +133,7 @@ "annual_report.summary.thanks": "sina lon kulupu Mastodon la sina pona a!", "attachments_list.unprocessed": "(nasin open)", "audio.hide": "o len e kalama", - "block_modal.remote_users_caveat": "mi pana e wile sina tawa ma {domain}. taso, o sona: ma li ken kepeken nasin len ante la pakala li ken lon. toki pi lukin ale la jan pi ma ala li ken lukin.", + "block_modal.remote_users_caveat": "mi pana e wile sina tawa ma {domain}. taso ma li ken kepeken nasin ante la pakala li ken. jan li awen ken lukin e toki kepeken sijelo ala.", "block_modal.show_less": "o lili e toki", "block_modal.show_more": "o suli e toki", "block_modal.they_cant_mention": "ona li ken ala toki tawa sina li ken ala kute e sina.", @@ -174,9 +174,9 @@ "column.edit_list": "o ante e kulupu", "column.favourites": "ijo pona", "column.firehose": "toki pi tenpo ni", - "column.firehose_local": "toki pi tenpo ni pi ma ni", + "column.firehose_local": "ma ni la toki pi tenpo ni", "column.firehose_singular": "toki pi tenpo ni", - "column.follow_requests": "wile alasa pi jan ante", + "column.follow_requests": "wile kute", "column.home": "lipu open", "column.list_members": "o ante e kulupu jan", "column.lists": "kulupu lipu", @@ -184,26 +184,26 @@ "column.notifications": "mu pi sona sin", "column.pins": "toki sewi", "column.public": "toki pi ma poka ale", - "column_back_button.label": "o tawa monsi", - "column_header.hide_settings": "o len e lawa", + "column_back_button.label": "o weka", + "column_header.hide_settings": "o len e nasin lawa", "column_header.moveLeft_settings": "poki toki ni o tawa ni ←", "column_header.moveRight_settings": "poki toki ni o tawa ni →", "column_header.pin": "o sewi", - "column_header.show_settings": "o lukin e lawa", + "column_header.show_settings": "o lukin e nasin lawa", "column_header.unpin": "o sewi ala", "column_search.cancel": "o ala", "community.column_settings.local_only": "toki tan ni taso", "community.column_settings.media_only": "sitelen taso", "community.column_settings.remote_only": "toki tan ante taso", - "compose.error.blank_post": "toki ken ala jo e ala.", + "compose.error.blank_post": "toki li wile.", "compose.language.change": "o ante e nasin toki", "compose.language.search": "o alasa e nasin toki...", - "compose.published.body": "toki li pana.", + "compose.published.body": "mi pana e toki.", "compose.published.open": "o lukin", - "compose.saved.body": "ilo li awen e ijo pana sina.", - "compose_form.direct_message_warning_learn_more": "o kama sona", + "compose.saved.body": "mi awen e toki sina.", + "compose_form.direct_message_warning_learn_more": "o sona", "compose_form.encryption_warning": "ilo Mastodon la toki li len ala. o pana ala e sona suli pi ken pakala.", - "compose_form.lock_disclaimer": "lipu sina li open, li {locked} ala. jan ale li ken kama kute e sina, li ken lukin e toki sama ni.", + "compose_form.lock_disclaimer": "lipu sina li {locked} ala. jan ale li ken kama kute e sina li ken lukin e toki sama ni.", "compose_form.lock_disclaimer.lock": "pini", "compose_form.placeholder": "sina wile toki e seme?", "compose_form.poll.duration": "tenpo pana", diff --git a/app/javascript/mastodon/locales/ug.json b/app/javascript/mastodon/locales/ug.json index 3162ee7351..25010a8339 100644 --- a/app/javascript/mastodon/locales/ug.json +++ b/app/javascript/mastodon/locales/ug.json @@ -15,6 +15,18 @@ "account.cancel_follow_request": "ئەگىشىش ئىلتىماسىدىن ۋاز كەچ", "account.copy": "تەرجىمىھال ئۇلانمىسىنى كۆچۈر", "account.direct": "@{name} نى يوشۇرۇن ئاتا", + "account.edit_profile_short": "تەھرىر", + "account.follow_request_cancel_short": "ۋاز كەچ", + "account.follow_request_short": "ئىلتىماس", + "account.followers": "ئەگەشكۈچى", + "account.followers.empty": "تېخى ھېچكىم بۇ كىشىگە ئەگەشمىدى.", + "account.followers_counter": "{count, plural, one {{counter} ئەگەشكۈچى} other {{counter} ئەگەشكۈچى}}", + "account.followers_you_know_counter": "تونۇيدىغىنىڭىز {counter}", + "account.following": "ئەگىشىۋاتىدۇ", + "account.following_counter": "{count, plural, one {{counter} ئەگىشىۋاتىدۇ} other {{counter} ئەگىشىۋاتىدۇ}}", + "account.follows.empty": "بۇ ئىشلەتكۈچى تېخى ھېچكىمگە ئەگەشمىدى.", + "account.follows_you": "سىزگە ئەگەشتى", + "account.go_to_profile": "تەرجىمىھالغا يۆتكەل", "account.posts": "يازما", "account.posts_with_replies": "يازما ۋە ئىنكاس", "account.report": "@{name} نى پاش قىل", diff --git a/app/javascript/mastodon/locales/vi.json b/app/javascript/mastodon/locales/vi.json index 5f4887267b..79528fb9f6 100644 --- a/app/javascript/mastodon/locales/vi.json +++ b/app/javascript/mastodon/locales/vi.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "tút mới", "annual_report.summary.percentile.text": "Bạn thuộc topthành viên của {domain}.", "annual_report.summary.percentile.we_wont_tell_bernie": "Chúng tôi sẽ không kể cho Bernie.", + "annual_report.summary.share_message": "Tôi là điển hình {archetype}!", "annual_report.summary.thanks": "Cảm ơn đã trở thành một phần của Mastodon!", "attachments_list.unprocessed": "(chưa xử lí)", "audio.hide": "Ẩn âm thanh", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index 1f65a846ad..274d3bc598 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "新嘟文", "annual_report.summary.percentile.text": "这使你跻身 {domain} 用户的前", "annual_report.summary.percentile.we_wont_tell_bernie": " ", + "annual_report.summary.share_message": "我今年的画像是{archetype}!", "annual_report.summary.thanks": "感谢您成为 Mastodon 的一员!", "attachments_list.unprocessed": "(未处理)", "audio.hide": "隐藏音频", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 27a057c28b..539d02ce5a 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -135,6 +135,7 @@ "annual_report.summary.new_posts.new_posts": "新嘟文", "annual_report.summary.percentile.text": "這讓您成為前{domain} 的使用者。", "annual_report.summary.percentile.we_wont_tell_bernie": "我們不會告訴 Bernie。", + "annual_report.summary.share_message": "我獲得 {archetype} 稱號!", "annual_report.summary.thanks": "感謝您成為 Mastodon 的一份子!", "attachments_list.unprocessed": "(未處理)", "audio.hide": "隱藏音訊", diff --git a/app/javascript/mastodon/reducers/slices/annual_report.ts b/app/javascript/mastodon/reducers/slices/annual_report.ts index db1c064e71..c01b8f7995 100644 --- a/app/javascript/mastodon/reducers/slices/annual_report.ts +++ b/app/javascript/mastodon/reducers/slices/annual_report.ts @@ -1,5 +1,10 @@ +import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; +import { + importFetchedAccounts, + importFetchedStatuses, +} from '@/mastodon/actions/importer'; import { insertIntoTimeline } from '@/mastodon/actions/timelines'; import type { ApiAnnualReportState } from '@/mastodon/api/annual_report'; import { @@ -25,7 +30,12 @@ interface AnnualReportState { const annualReportSlice = createSlice({ name: 'annualReport', initialState: {} as AnnualReportState, - reducers: {}, + reducers: { + setReport(state, action: PayloadAction) { + state.report = action.payload; + state.state = 'available'; + }, + }, extraReducers(builder) { builder .addCase(fetchReportState.fulfilled, (state, action) => { @@ -43,6 +53,7 @@ const annualReportSlice = createSlice({ }); export const annualReport = annualReportSlice.reducer; +export const { setReport } = annualReportSlice.actions; export const selectWrapstodonYear = createAppSelector( [(state) => state.server.getIn(['server', 'wrapstodon'])], @@ -114,5 +125,9 @@ export const getReport = createDataLoadingThunk( } return apiGetAnnualReport(year); }, - (data) => data.annual_reports[0], + (data, { dispatch }) => { + dispatch(importFetchedStatuses(data.statuses)); + dispatch(importFetchedAccounts(data.accounts)); + return data.annual_reports[0]; + }, ); diff --git a/app/javascript/styles/mastodon-light/css_variables.scss b/app/javascript/styles/mastodon-light/css_variables.scss index 70745ec071..a96773f76c 100644 --- a/app/javascript/styles/mastodon-light/css_variables.scss +++ b/app/javascript/styles/mastodon-light/css_variables.scss @@ -39,6 +39,7 @@ var(--color-text-brand) ); --color-text-on-brand-base: var(--color-white); + --color-text-brand-on-inverted: var(--color-indigo-400); --color-text-error: var(--color-red-600); --color-text-on-error-base: var(--color-white); --color-text-warning: var(--color-yellow-600); diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 01de2c7d7a..ed2403b045 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -10267,7 +10267,7 @@ noscript { background: transparent; text-transform: uppercase; cursor: pointer; - color: var(--color-text-brand); + color: var(--color-text-brand-on-inverted); font-weight: 700; border-radius: 4px; padding: 0 4px; @@ -10751,7 +10751,7 @@ noscript { box-sizing: border-box; font-size: 14px; color: var(--color-text-secondary); - background: var(--color-bg-tertiary); + background: var(--color-bg-secondary); border: 1px solid var(--color-border-primary); border-top: 0; border-radius: 0 0 8px 8px; diff --git a/app/javascript/styles/mastodon/css_variables.scss b/app/javascript/styles/mastodon/css_variables.scss index b270bd337f..98b61d2f0b 100644 --- a/app/javascript/styles/mastodon/css_variables.scss +++ b/app/javascript/styles/mastodon/css_variables.scss @@ -39,6 +39,7 @@ var(--color-text-brand) ); --color-text-on-brand-base: var(--color-white); + --color-text-brand-on-inverted: var(--color-indigo-600); --color-text-error: var(--color-red-500); --color-text-on-error-base: var(--color-white); --color-text-warning: var(--color-yellow-400); @@ -60,7 +61,7 @@ // Neutrals --color-bg-primary: var(--color-grey-950); - --overlay-strength-secondary: 10%; + --overlay-strength-secondary: 8%; --color-bg-secondary-base: var(--color-indigo-200); --color-bg-secondary: #{utils.css-alpha( var(--color-bg-secondary-base), diff --git a/app/lib/annual_report.rb b/app/lib/annual_report.rb index 12d69dfba8..0acd51eb17 100644 --- a/app/lib/annual_report.rb +++ b/app/lib/annual_report.rb @@ -22,7 +22,7 @@ class AnnualReport return unless Mastodon::Feature.wrapstodon_enabled? datetime = Time.now.utc - datetime.year if datetime.month == 12 && (10..31).cover?(datetime.day) + datetime.year if datetime.month == 12 && (1..31).cover?(datetime.day) end def initialize(account, year) diff --git a/app/lib/status_cache_hydrator.rb b/app/lib/status_cache_hydrator.rb index be425e1291..b830e509bf 100644 --- a/app/lib/status_cache_hydrator.rb +++ b/app/lib/status_cache_hydrator.rb @@ -26,12 +26,7 @@ class StatusCacheHydrator def hydrate_non_reblog_payload(empty_payload, account_id, nested: false) empty_payload.tap do |payload| - fill_status_payload(payload, @status, account_id, nested:) - - if payload[:poll] - payload[:poll][:voted] = @status.account_id == account_id - payload[:poll][:own_votes] = [] - end + fill_status_payload(payload, @status, account_id, fresh: !nested, nested:) end end @@ -45,18 +40,7 @@ class StatusCacheHydrator # used to create the status, we need to hydrate it here too payload[:reblog][:application] = payload_reblog_application if payload[:reblog][:application].nil? && @status.reblog.account_id == account_id - fill_status_payload(payload[:reblog], @status.reblog, account_id, nested:) - - if payload[:reblog][:poll] - if @status.reblog.account_id == account_id - payload[:reblog][:poll][:voted] = true - payload[:reblog][:poll][:own_votes] = [] - else - own_votes = PollVote.where(poll_id: @status.reblog.poll_id, account_id: account_id).pluck(:choice) - payload[:reblog][:poll][:voted] = !own_votes.empty? - payload[:reblog][:poll][:own_votes] = own_votes - end - end + fill_status_payload(payload[:reblog], @status.reblog, account_id, fresh: false, nested:) payload[:filtered] = payload[:reblog][:filtered] payload[:favourited] = payload[:reblog][:favourited] @@ -65,7 +49,7 @@ class StatusCacheHydrator end end - def fill_status_payload(payload, status, account_id, nested: false) + def fill_status_payload(payload, status, account_id, nested: false, fresh: true) payload[:favourited] = Favourite.exists?(account_id: account_id, status_id: status.id) payload[:reblogged] = Status.exists?(account_id: account_id, reblog_of_id: status.id) payload[:muted] = ConversationMute.exists?(account_id: account_id, conversation_id: status.conversation_id) @@ -76,6 +60,21 @@ class StatusCacheHydrator payload[:quote_approval][:current_user] = status.quote_policy_for_account(Account.find_by(id: account_id)) if payload[:quote_approval] payload[:quote] = hydrate_quote_payload(payload[:quote], status.quote, account_id, nested:) if payload[:quote] + if payload[:poll] + if fresh + # If the status is brand new, we don't need to look up votes in database + payload[:poll][:voted] = status.account_id == account_id + payload[:poll][:own_votes] = [] + elsif status.account_id == account_id + payload[:poll][:voted] = true + payload[:poll][:own_votes] = [] + else + own_votes = PollVote.where(poll_id: status.poll_id, account_id: account_id).pluck(:choice) + payload[:poll][:voted] = !own_votes.empty? + payload[:poll][:own_votes] = own_votes + end + end + # Nested statuses are more likely to have a stale cache fill_status_stats(payload, status) if nested end diff --git a/app/models/collection.rb b/app/models/collection.rb index 308e517e26..79af2967c1 100644 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -50,12 +50,20 @@ class Collection < ApplicationRecord result end + def tag_name + tag&.formatted_name + end + + def tag_name=(new_name) + self.tag = Tag.find_or_create_by_names(new_name).first + end + private def tag_is_usable return if tag.blank? - errors.add(:tag, :unusable) unless tag.usable? + errors.add(:tag_name, :unusable) unless tag.usable? end def items_do_not_exceed_limit diff --git a/app/models/tag.rb b/app/models/tag.rb index c59b0f36a8..9924d132e6 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -67,6 +67,8 @@ class Tag < ApplicationRecord } scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index + normalizes :display_name, with: ->(value) { value.gsub(HASHTAG_INVALID_CHARS_RE, '') } + update_index('tags', :self) def to_param @@ -113,10 +115,7 @@ class Tag < ApplicationRecord names.map do |(normalized_name, display_name)| tag = begin - matching_name(normalized_name).first || create!( - name: normalized_name, - display_name: display_name.gsub(HASHTAG_INVALID_CHARS_RE, '') - ) + matching_name(normalized_name).first || create!(name: normalized_name, display_name:) rescue ActiveRecord::RecordNotUnique find_normalized(normalized_name) end diff --git a/app/policies/collection_policy.rb b/app/policies/collection_policy.rb new file mode 100644 index 0000000000..12adfbcad1 --- /dev/null +++ b/app/policies/collection_policy.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class CollectionPolicy < ApplicationPolicy + def index? + true + end + + def show? + true + end + + def create? + user_signed_in? + end + + def update? + owner? + end + + def destroy? + owner? + end + + private + + def owner? + current_account == record.account + end +end diff --git a/app/services/create_collection_service.rb b/app/services/create_collection_service.rb index 5cf7249fee..92c26879d1 100644 --- a/app/services/create_collection_service.rb +++ b/app/services/create_collection_service.rb @@ -2,9 +2,8 @@ class CreateCollectionService def call(params, account) - tag = params.delete(:tag) account_ids = params.delete(:account_ids) - @collection = Collection.new(params.merge({ account:, local: true, tag: find_or_create_tag(tag) })) + @collection = Collection.new(params.merge({ account:, local: true })) build_items(account_ids) @collection.save! @@ -13,12 +12,6 @@ class CreateCollectionService private - def find_or_create_tag(name) - return nil if name.blank? - - Tag.find_or_create_by_names(name).first - end - def build_items(account_ids) return if account_ids.blank? diff --git a/app/views/wrapstodon/show.html.haml b/app/views/wrapstodon/show.html.haml index 6978f231f9..70c8c77b19 100644 --- a/app/views/wrapstodon/show.html.haml +++ b/app/views/wrapstodon/show.html.haml @@ -6,4 +6,7 @@ = opengraph 'og:site_name', site_title = opengraph 'profile:username', acct(@account)[1..] -= render 'shared/web_app' + = vite_typescript_tag 'wrapstodon.tsx', crossorigin: 'anonymous' + +#wrapstodon += render_wrapstodon_share_data @generated_annual_report diff --git a/config/locales/be.yml b/config/locales/be.yml index 003902d8ec..c8ba5dde06 100644 --- a/config/locales/be.yml +++ b/config/locales/be.yml @@ -1784,16 +1784,22 @@ be: body: 'Вас згадаў %{name} у:' subject: Вас згадаў %{name} title: Новае згадванне + moderation_warning: + subject: Вы атрымалі папярэджанне ад мадэратараў poll: subject: Апытанне ад %{name} скончылася quote: body: 'Ваш допіс працытаваў карыстальнік %{name}:' subject: Карыстальнік %{name} працытаваў Ваш допіс title: Цытаваць + quoted_update: + subject: "%{name} адрэдагаваў допіс, як Вы цытавалі" reblog: body: "%{name} пашырыў(-ла) Ваш допіс:" subject: "%{name} пашырыў ваш допіс" title: Новае пашырэнне + severed_relationships: + subject: Вы страцілі сувязі праз рашэнне мадэратараў status: subject: Новы допіс ад %{name} update: diff --git a/config/locales/ca.yml b/config/locales/ca.yml index aa1cc97dbb..bc7cd7673a 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -1684,16 +1684,22 @@ ca: body: "%{name} t'ha mencionat en:" subject: "%{name} t'ha mencionat" title: Nova menció + moderation_warning: + subject: Heu rebut un avís de moderació poll: subject: Ha finalitzat l'enquesta de %{name} quote: body: 'La vostra publicació ha estat citada per %{name}:' subject: "%{name} ha citat la vostra publicació" title: Nova citació + quoted_update: + subject: "%{name} ha editat una publicació que heu citat" reblog: body: "%{name} ha impulsat el teu estat:" subject: "%{name} ha impulsat el teu estat" title: Nou impuls + severed_relationships: + subject: Heu perdut connexions degut a una decisió de moderació status: subject: "%{name} ha publicat" update: @@ -2153,3 +2159,5 @@ ca: not_supported: Aquest navegador no suporta claus de seguretat otp_required: Per a usar claus de seguretat, activeu primer l'autenticació de dos factors. registered_on: Registrat en %{date} + wrapstodon: + title: Wrapstodon %{year} per a %{name} diff --git a/config/locales/da.yml b/config/locales/da.yml index caddba755d..09bcb6fdf0 100644 --- a/config/locales/da.yml +++ b/config/locales/da.yml @@ -2185,3 +2185,5 @@ da: not_supported: Denne browser understøtter ikke sikkerhedsnøgler otp_required: For at bruge sikkerhedsnøgler skal tofaktorgodkendelse først aktiveres. registered_on: Registreret d. %{date} + wrapstodon: + title: Wrapstodon %{year} for %{name} diff --git a/config/locales/de.yml b/config/locales/de.yml index d9473031c8..3ec274dc47 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -1720,6 +1720,8 @@ de: body: 'Dein Beitrag wurde von %{name} geteilt:' subject: "%{name} teilte deinen Beitrag" title: Dein Beitrag wurde geteilt + severed_relationships: + subject: Du hast die Verbindung aufgrund einer Moderationsentscheidung verloren status: subject: "%{name} veröffentlichte gerade einen Beitrag" update: @@ -2183,3 +2185,5 @@ de: not_supported: Dieser Browser unterstützt keine Sicherheitsschlüssel otp_required: Um Sicherheitsschlüssel zu verwenden, aktiviere zunächst die Zwei-Faktor-Authentisierung. registered_on: Registriert am %{date} + wrapstodon: + title: Wrapstodon %{year} für %{name} diff --git a/config/locales/el.yml b/config/locales/el.yml index 259a3f7ff1..a17c20bdec 100644 --- a/config/locales/el.yml +++ b/config/locales/el.yml @@ -2185,3 +2185,5 @@ el: not_supported: Αυτό το πρόγραμμα περιήγησης δεν υποστηρίζει κλειδιά ασφαλείας otp_required: Για να χρησιμοποιήσεις κλειδιά ασφαλείας, ενεργοποίησε πρώτα την ταυτοποίηση δύο παραγόντων. registered_on: Εγγραφή στις %{date} + wrapstodon: + title: Wrapstodon %{year} για %{name} diff --git a/config/locales/es-AR.yml b/config/locales/es-AR.yml index da522bee6a..097329cc5b 100644 --- a/config/locales/es-AR.yml +++ b/config/locales/es-AR.yml @@ -2185,3 +2185,5 @@ es-AR: not_supported: Este navegador web no soporta llaves de seguridad otp_required: Para usar llaves de seguridad, por favor, primero habilitá la autenticación de dos factores. registered_on: Registrado el %{date} + wrapstodon: + title: MastodonAnual %{year} para %{name} diff --git a/config/locales/es-MX.yml b/config/locales/es-MX.yml index 7b67ef01ff..0ca9c86c04 100644 --- a/config/locales/es-MX.yml +++ b/config/locales/es-MX.yml @@ -1720,6 +1720,8 @@ es-MX: body: 'Tu publicación fue impulsada por %{name}:' subject: "%{name} ha impulsado tu publicación" title: Nuevo impulso + severed_relationships: + subject: Has perdido conexiones debido a una decisión de moderación status: subject: "%{name} acaba de publicar" update: @@ -2183,3 +2185,5 @@ es-MX: not_supported: Este navegador no soporta claves de seguridad otp_required: Para usar claves de seguridad, por favor habilite primero la autenticación de doble factor. registered_on: Registrado el %{date} + wrapstodon: + title: Wrapstodon %{year} para %{name} diff --git a/config/locales/es.yml b/config/locales/es.yml index c7268deb92..1dd2760b40 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1720,6 +1720,8 @@ es: body: 'Tu publicación fue impulsada por %{name}:' subject: "%{name} impulsó tu publicación" title: Nueva difusión + severed_relationships: + subject: Has perdido conexiones debido a una decisión de moderación status: subject: "%{name} acaba de publicar" update: @@ -2183,3 +2185,5 @@ es: not_supported: Este navegador no soporta claves de seguridad otp_required: Para usar claves de seguridad, por favor habilite primero la autenticación de doble factor. registered_on: Registrado el %{date} + wrapstodon: + title: Wrapstodon %{year} para %{name} diff --git a/config/locales/fo.yml b/config/locales/fo.yml index 82c21360e6..a94f0d1fed 100644 --- a/config/locales/fo.yml +++ b/config/locales/fo.yml @@ -1706,16 +1706,22 @@ fo: body: 'Tú var umrødd/ur av %{name} í:' subject: Tú var umrødd/ur av %{name} title: Nýggj umrøða + moderation_warning: + subject: Tú hevur móttikið eina umsjónarávaring poll: subject: Ein spurnarkanning hjá %{name} er endað quote: body: 'Postur tín var siteraður av %{name}:' subject: "%{name} siteraði postin hjá tær" title: Nýggj sitering + quoted_update: + subject: "%{name} rættaði ein post, sum tú hevur siterað" reblog: body: 'Postur tín var stimbraður av %{name}:' subject: "%{name} stimbraði tín post" title: Nýggj stimbran + severed_relationships: + subject: Tú hevur mist sambond vegna eina umsjónaravgerð status: subject: "%{name} hevur júst postað" update: @@ -2179,3 +2185,5 @@ fo: not_supported: Hesin kagin stuðlar ikki uppundir trygdarlyklar otp_required: Fyri at brúka trygdarlyklar er neyðugt at gera váttan í tveimum stigum virkna fyrst. registered_on: Skrásett %{date} + wrapstodon: + title: Wrapstodon %{year} fyri %{name} diff --git a/config/locales/fr-CA.yml b/config/locales/fr-CA.yml index 3a46a17f55..78e0d4263a 100644 --- a/config/locales/fr-CA.yml +++ b/config/locales/fr-CA.yml @@ -1709,16 +1709,22 @@ fr-CA: body: "%{name} vous a mentionné⋅e dans :" subject: "%{name} vous a mentionné·e" title: Nouvelle mention + moderation_warning: + subject: Vous avez reçu un avertissement de la modération poll: subject: Un sondage de %{name} est terminé quote: body: 'Votre message a été cité par %{name}:' subject: "%{name} a cité votre message" title: Nouvelle citation + quoted_update: + subject: "%{name} a modifié un message que vous avez cité" reblog: body: 'Votre message été partagé par %{name} :' subject: "%{name} a partagé votre message" title: Nouveau partage + severed_relationships: + subject: Vous avez perdu des relations à cause d’une décision de modération status: subject: "%{name} vient de publier" update: @@ -2182,3 +2188,5 @@ fr-CA: not_supported: Ce navigateur ne prend pas en charge les clés de sécurité otp_required: Pour utiliser les clés de sécurité, veuillez d'abord activer l'authentification à deux facteurs. registered_on: Inscrit le %{date} + wrapstodon: + title: Wrapstodon %{year} pour %{name} diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 28be8c9641..0767c223bb 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -1709,16 +1709,22 @@ fr: body: "%{name} vous a mentionné⋅e dans :" subject: "%{name} vous a mentionné·e" title: Nouvelle mention + moderation_warning: + subject: Vous avez reçu un avertissement de la modération poll: subject: Un sondage de %{name} est terminé quote: body: 'Votre message a été cité par %{name}:' subject: "%{name} a cité votre message" title: Nouvelle citation + quoted_update: + subject: "%{name} a modifié un message que vous avez cité" reblog: body: 'Votre message été partagé par %{name} :' subject: "%{name} a partagé votre message" title: Nouveau partage + severed_relationships: + subject: Vous avez perdu des relations à cause d’une décision de modération status: subject: "%{name} vient de publier" update: @@ -2182,3 +2188,5 @@ fr: not_supported: Ce navigateur ne prend pas en charge les clés de sécurité otp_required: Pour utiliser les clés de sécurité, veuillez d'abord activer l'authentification à deux facteurs. registered_on: Inscrit le %{date} + wrapstodon: + title: Wrapstodon %{year} pour %{name} diff --git a/config/locales/ga.yml b/config/locales/ga.yml index aac1e85e88..9c5ea95f84 100644 --- a/config/locales/ga.yml +++ b/config/locales/ga.yml @@ -1825,16 +1825,22 @@ ga: body: 'Luaigh %{name} thú i:' subject: Luaigh %{name} thú title: Lua nua + moderation_warning: + subject: Tá rabhadh modhnóireachta faighte agat poll: subject: Tháinig deireadh le vótaíocht le %{name} quote: body: 'Luaigh %{name} do phost:' subject: Luaigh %{name} do phost title: Luachan nua + quoted_update: + subject: Chuir %{name} post in eagar a luaigh tú reblog: body: 'Treisíodh do phostáil le %{name}:' subject: Mhol %{name} do phostáil title: Moladh nua + severed_relationships: + subject: Tá naisc caillte agat mar gheall ar chinneadh modhnóireachta status: subject: Tá %{name} díreach postáilte update: @@ -2313,3 +2319,5 @@ ga: not_supported: Ní thacaíonn an brabhsálaí seo le heochracha slándála otp_required: Chun eochracha slándála a úsáid cumasaigh fíordheimhniú dhá fhachtóir ar dtús. registered_on: Cláraithe ar %{date} + wrapstodon: + title: Wrapstodon %{year} do %{name} diff --git a/config/locales/gl.yml b/config/locales/gl.yml index e2954e5538..52db9182d7 100644 --- a/config/locales/gl.yml +++ b/config/locales/gl.yml @@ -1706,16 +1706,22 @@ gl: body: "%{name} mencionoute en:" subject: Foches mencionada por %{name} title: Nova mención + moderation_warning: + subject: Recibiches unha advertencia da moderación poll: subject: A enquisa de %{name} rematou quote: body: 'A túa publicación foi citada por %{name}:' subject: "%{name} citou a túa publicación" title: Nova cita + quoted_update: + subject: "%{name} editou unha publicación que citaches" reblog: body: 'A túa publicación promovida por %{name}:' subject: "%{name} promoveu a túa publicación" title: Nova promoción + severed_relationships: + subject: Perdeches algunhas relacións debido a decisións da moderación status: subject: "%{name} publicou" update: diff --git a/config/locales/he.yml b/config/locales/he.yml index 584193d981..6550f17cf5 100644 --- a/config/locales/he.yml +++ b/config/locales/he.yml @@ -2273,3 +2273,5 @@ he: not_supported: דפדפן זה לא תומך במפתחות אבטחה otp_required: על מנת להשתמש במפתחות אבטחה אנא אפשר.י אימות דו-שלבי קודם. registered_on: נרשם ב %{date} + wrapstodon: + title: סיכומודון %{year} עבור %{name} diff --git a/config/locales/hu.yml b/config/locales/hu.yml index ab49a9b231..abaa78e1e4 100644 --- a/config/locales/hu.yml +++ b/config/locales/hu.yml @@ -1707,17 +1707,21 @@ hu: subject: "%{name} megemlített téged" title: Új említés moderation_warning: - subject: Kaptál egy moderálási figyelmeztetést + subject: Moderációs figyelmeztetést kaptál poll: subject: "%{name} szavazása véget ért" quote: body: 'A bejegyzésedet %{name} idézte:' subject: "%{name} idézte a bejegyzésedet" title: Új idézet + quoted_update: + subject: "%{name} szerkesztett egy bejegyzést, melyet idéztél" reblog: body: 'A bejegyzésedet %{name} megtolta:' subject: "%{name} megtolta a bejegyzésedet" title: Új megtolás + severed_relationships: + subject: Moderációs döntés miatt kapcsolatokat veszítettél status: subject: "%{name} bejegyzést írt" update: diff --git a/config/locales/is.yml b/config/locales/is.yml index cec2023a87..f964c1ad2e 100644 --- a/config/locales/is.yml +++ b/config/locales/is.yml @@ -2189,3 +2189,5 @@ is: not_supported: Þessi vafri styður ekki öryggislykla otp_required: Til að nota öryggislykla skaltu fyrst virkja tveggja-þátta auðkenningu. registered_on: Skráði sig %{date} + wrapstodon: + title: Wrapstodon %{year} fyrir %{name} diff --git a/config/locales/ja.yml b/config/locales/ja.yml index f15f97ee9b..c9d4642d5a 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -1694,6 +1694,8 @@ ja: too_few_options: は複数必要です too_many_options: は%{max}個までです vote: 投票 + posting_defaults: + explanation: これらの設定は投稿を新規作成するときにデフォルトとして使用されますが、作成画面で投稿ごとに変更できます。 preferences: other: その他 posting_defaults: デフォルトの投稿設定 diff --git a/config/locales/pt-BR.yml b/config/locales/pt-BR.yml index 4dea9d51d2..657ab9f6ad 100644 --- a/config/locales/pt-BR.yml +++ b/config/locales/pt-BR.yml @@ -2186,3 +2186,5 @@ pt-BR: not_supported: Este navegador não tem suporte a chaves de segurança otp_required: Para usar chaves de segurança, ative a autenticação de dois fatores. registered_on: Registrado em %{date} + wrapstodon: + title: Wrapstodon de %{year} para %{name} diff --git a/config/locales/simple_form.ja.yml b/config/locales/simple_form.ja.yml index dc4bb1354f..34c1bcc8e4 100644 --- a/config/locales/simple_form.ja.yml +++ b/config/locales/simple_form.ja.yml @@ -54,6 +54,7 @@ ja: password: 少なくとも8文字は入力してください phrase: 投稿内容の大文字小文字や閲覧注意に関係なく一致 scopes: アプリの API に許可するアクセス権を選択してください。最上位のスコープを選択する場合、個々のスコープを選択する必要はありません。 + setting_advanced_layout: Mastodonを複数カラムのレイアウトで表示します。タイムライン、通知、そして好みのカラムを閲覧できます。小さい画面には非推奨です。 setting_aggregate_reblogs: 最近ブーストされた投稿が新たにブーストされても表示しません (設定後受信したものにのみ影響) setting_always_send_emails: 通常、Mastodon からメール通知は行われません。 setting_boost_modal: 有効にすると、ブーストによって、まず、ブーストの公開範囲を設定できる確認ダイアログが表示されます。 diff --git a/config/locales/simple_form.lt.yml b/config/locales/simple_form.lt.yml index 7010597754..fa40b11585 100644 --- a/config/locales/simple_form.lt.yml +++ b/config/locales/simple_form.lt.yml @@ -54,6 +54,7 @@ lt: password: Naudok bent 8 simbolius phrase: Bus suderinta, neatsižvelgiant į teksto lygį arba įrašo turinio įspėjimą scopes: Prie kurių API programai bus leidžiama pasiekti. Pasirinkus aukščiausio lygio sritį, atskirų sričių pasirinkti nereikia. + setting_advanced_layout: Rodykite „Mastodon“ kaip kelių stulpelių išdėstymą, leidžiantį peržiūrėti įrašų srautą, pranešimus ir trečiąjį stulpelį pagal savo pasirinkimą. Nerekomenduojama mažesniems ekranams. setting_aggregate_reblogs: Nerodyti naujų pakėlimų įrašams, kurie neseniai buvo pakelti (taikoma tik naujai gautiems pakėlimams). setting_always_send_emails: Paprastai el. laiško pranešimai nebus siunčiami, kai aktyviai naudoji Mastodon. setting_default_quote_policy_private: Tik sekėjams skirti įrašai, paskelbti platformoje „Mastodon“, negali būti cituojami kitų. diff --git a/config/locales/tr.yml b/config/locales/tr.yml index d0228c5cea..749088b719 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -2185,3 +2185,5 @@ tr: not_supported: Bu tarayıcı güvenlik anahtarlarını desteklemiyor otp_required: Güvenlik anahtarlarını kullanmak için lütfen önce iki adımlı kimlik doğrulamayı etkinleştirin. registered_on: "%{date} tarihinde kaydoldu" + wrapstodon: + title: "%{name} için %{year} Wrapstodon'u" diff --git a/config/locales/vi.yml b/config/locales/vi.yml index 0e39f6bf0f..59bd33fffd 100644 --- a/config/locales/vi.yml +++ b/config/locales/vi.yml @@ -2141,3 +2141,5 @@ vi: not_supported: Trình duyệt của bạn không hỗ trợ khóa bảo mật otp_required: Để dùng khóa bảo mật, trước tiên hãy kích hoạt xác thực 2 bước. registered_on: Đăng ký vào %{date} + wrapstodon: + title: Wrapstodon %{year} cho %{name} diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index c7a1fc84a6..bfe2c9917a 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -2141,3 +2141,5 @@ zh-CN: not_supported: 此浏览器不支持安全密钥 otp_required: 要使用安全密钥,请先启用双因素认证。 registered_on: 注册于 %{date} + wrapstodon: + title: "%{name}的%{year}年Wrapstodon年度回顾" diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml index e7f8172aee..ec19a24247 100644 --- a/config/locales/zh-TW.yml +++ b/config/locales/zh-TW.yml @@ -2147,3 +2147,5 @@ zh-TW: not_supported: 此瀏覽器並不支援安全金鑰 otp_required: 請先啟用兩階段驗證以使用安全金鑰。 registered_on: 註冊於 %{date} + wrapstodon: + title: "%{name} 的 %{year} Mastodon 年度回顧 (Wrapstodon)" diff --git a/config/routes/api.rb b/config/routes/api.rb index 9bf23c5238..86b3946e4c 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -8,7 +8,7 @@ namespace :api, format: false do namespace :v1_alpha do resources :async_refreshes, only: :show - resources :collections, only: [:show, :create] + resources :collections, only: [:show, :create, :update, :destroy] end # JSON / REST API diff --git a/package.json b/package.json index 97077b2751..1b5019c7b2 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@formatjs/intl-pluralrules": "^5.4.4", "@gamestdio/websocket": "^0.3.2", "@github/webauthn-json": "^2.1.1", - "@optimize-lodash/rollup-plugin": "^5.0.2", + "@optimize-lodash/rollup-plugin": "^6.0.0", "@react-spring/web": "^9.7.5", "@reduxjs/toolkit": "^2.0.1", "@use-gesture/react": "^10.3.1", diff --git a/spec/lib/status_cache_hydrator_spec.rb b/spec/lib/status_cache_hydrator_spec.rb index 085866ef1d..8ad4e5614e 100644 --- a/spec/lib/status_cache_hydrator_spec.rb +++ b/spec/lib/status_cache_hydrator_spec.rb @@ -176,6 +176,28 @@ RSpec.describe StatusCacheHydrator do end end + context 'when the quoted post has a poll authored by the user' do + let(:poll) { Fabricate(:poll, account: account) } + let(:quoted_status) { Fabricate(:status, poll: poll, account: account) } + + it 'renders the same attributes as a full render' do + expect(subject).to eql(compare_to_hash) + end + end + + context 'when the quoted post has been voted in' do + let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) } + let(:quoted_status) { Fabricate(:status, poll: poll) } + + before do + VoteService.new.call(account, poll, [0]) + end + + it 'renders the same attributes as a full render' do + expect(subject).to eql(compare_to_hash) + end + end + context 'when the quoted post matches account filters' do let(:quoted_status) { Fabricate(:status, text: 'this toot is about that banned word') } diff --git a/spec/models/collection_spec.rb b/spec/models/collection_spec.rb index 3d367b9d90..659e017869 100644 --- a/spec/models/collection_spec.rb +++ b/spec/models/collection_spec.rb @@ -72,4 +72,58 @@ RSpec.describe Collection do end end end + + describe '#tag_name=' do + context 'when the collection is new and has no tag' do + subject { Fabricate.build(:collection) } + + context 'when the tag exists' do + let!(:tag) { Fabricate.create(:tag, name: 'people') } + + it 'correctly assigns the existing tag' do + subject.tag_name = '#people' + + expect(subject.tag).to eq tag + end + end + + context 'when the tag does not exist' do + it 'creates and assigns a new tag' do + expect do + subject.tag_name = '#people' + end.to change(Tag, :count).by(1) + + expect(subject.tag).to be_present + expect(subject.tag.name).to eq 'people' + end + end + end + + context 'when the collection is persisted and has a tag' do + subject { Fabricate(:collection, tag:) } + + let!(:tag) { Fabricate(:tag, name: 'people') } + + context 'when the new tag is the same' do + it 'does not change the object' do + subject.tag_name = '#People' + + expect(subject.tag).to eq tag + expect(subject).to_not be_changed + end + end + + context 'when the new tag is different' do + it 'creates and assigns a new tag' do + expect do + subject.tag_name = '#bots' + end.to change(Tag, :count).by(1) + + expect(subject.tag).to be_present + expect(subject.tag.name).to eq 'bots' + expect(subject).to be_changed + end + end + end + end end diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb index 9a68ae36d6..79f8edf79a 100644 --- a/spec/models/tag_spec.rb +++ b/spec/models/tag_spec.rb @@ -57,6 +57,11 @@ RSpec.describe Tag do end end + describe 'Normalizations' do + it { is_expected.to normalize(:display_name).from('#HelloWorld').to('HelloWorld') } + it { is_expected.to normalize(:display_name).from('Hello❤️World').to('HelloWorld') } + end + describe 'HASHTAG_RE' do subject { described_class::HASHTAG_RE } @@ -251,17 +256,29 @@ RSpec.describe Tag do end describe '.find_or_create_by_names' do - let(:upcase_string) { 'abcABCabcABCやゆよ' } - let(:downcase_string) { 'abcabcabcabcやゆよ' } + context 'when called with a block' do + let(:upcase_string) { 'abcABCabcABCやゆよ' } + let(:downcase_string) { 'abcabcabcabcやゆよ' } + let(:args) { [upcase_string, downcase_string] } - it 'runs a passed block once per tag regardless of duplicates' do - count = 0 - - described_class.find_or_create_by_names([upcase_string, downcase_string]) do |_tag| - count += 1 + it 'runs the block once per normalized tag regardless of duplicates' do + expect { |block| described_class.find_or_create_by_names(args, &block) } + .to yield_control.once end + end - expect(count).to eq 1 + context 'when passed an array' do + it 'creates multiples tags' do + expect { described_class.find_or_create_by_names(%w(tips tags toes)) } + .to change(described_class, :count).by(3) + end + end + + context 'when passed a string' do + it 'creates a single tag' do + expect { described_class.find_or_create_by_names('test') } + .to change(described_class, :count).by(1) + end end end @@ -270,16 +287,10 @@ RSpec.describe Tag do tag_name_upper = 'Rails' tag_name_lower = 'rails' - threads = [] - - 2.times do |i| - threads << Thread.new do - described_class.find_or_create_by_names(i.zero? ? tag_name_upper : tag_name_lower) - end + multi_threaded_execution(2) do |index| + described_class.find_or_create_by_names(index.zero? ? tag_name_upper : tag_name_lower) end - threads.each(&:join) - tags = described_class.where('lower(name) = ?', tag_name_lower.downcase) expect(tags.count).to eq(1) expect(tags.first.name.downcase).to eq(tag_name_lower.downcase) diff --git a/spec/policies/collection_policy_spec.rb b/spec/policies/collection_policy_spec.rb new file mode 100644 index 0000000000..156e1a7657 --- /dev/null +++ b/spec/policies/collection_policy_spec.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe CollectionPolicy do + let(:policy) { described_class } + let(:collection) { Fabricate(:collection) } + let(:owner) { collection.account } + let(:other_user) { Fabricate(:account) } + + permissions :index? do + it 'permits everyone to index' do + expect(policy).to permit(nil, Collection) + expect(policy).to permit(owner, Collection) + end + end + + permissions :show? do + it 'permits everyone to show' do + expect(policy).to permit(nil, collection) + expect(policy).to permit(owner, collection) + expect(policy).to permit(other_user, collection) + end + end + + permissions :create? do + it 'permits any user' do + expect(policy).to_not permit(nil, Collection) + + expect(policy).to permit(owner, Collection) + expect(policy).to permit(other_user, Collection) + end + end + + permissions :update?, :destroy? do + it 'only permits the owner' do + expect(policy).to_not permit(nil, collection) + expect(policy).to_not permit(other_user, collection) + + expect(policy).to permit(owner, collection) + end + end +end diff --git a/spec/requests/api/v1_alpha/collections_spec.rb b/spec/requests/api/v1_alpha/collections_spec.rb index d576fbf98b..c0472d2f48 100644 --- a/spec/requests/api/v1_alpha/collections_spec.rb +++ b/spec/requests/api/v1_alpha/collections_spec.rb @@ -95,4 +95,103 @@ RSpec.describe 'Api::V1Alpha::Collections', feature: :collections do end end end + + describe 'PATCH /api/v1_alpha/collections/:id' do + subject do + patch "/api/v1_alpha/collections/#{collection.id}", headers: headers, params: params + end + + let(:collection) { Fabricate(:collection) } + let(:params) { {} } + + context 'when user is not owner' do + it 'returns http forbidden' do + subject + + expect(response).to have_http_status(403) + end + end + + context 'when user is the owner' do + let(:collection) do + Fabricate(:collection, + account: user.account, + name: 'Pople to follow', + description: 'Cool pople', + sensitive: true, + discoverable: false) + end + + it_behaves_like 'forbidden for wrong scope', 'read:collections' + + context 'with valid params' do + let(:params) do + { + name: 'People to follow', + description: 'Cool people', + sensitive: '0', + discoverable: '1', + } + end + + it 'updates the collection and returns http success' do + subject + collection.reload + + expect(response).to have_http_status(200) + expect(collection.name).to eq 'People to follow' + expect(collection.description).to eq 'Cool people' + expect(collection.sensitive).to be false + expect(collection.discoverable).to be true + end + end + + context 'with invalid params' do + let(:params) { { name: '' } } + + it 'returns http unprocessable content and detailed errors' do + subject + + expect(response).to have_http_status(422) + expect(response.parsed_body).to include({ + 'error' => a_hash_including({ + 'details' => a_hash_including({ + 'name' => [{ 'error' => 'ERR_BLANK', 'description' => "can't be blank" }], + }), + }), + }) + end + end + end + end + + describe 'DELETE /api/v1_alpha/collections/:id' do + subject do + delete "/api/v1_alpha/collections/#{collection.id}", headers: headers + end + + let(:collection) { Fabricate(:collection) } + + context 'when user is not owner' do + it 'returns http forbidden' do + subject + + expect(response).to have_http_status(403) + end + end + + context 'when user is the owner' do + let(:collection) { Fabricate(:collection, account: user.account) } + + it_behaves_like 'forbidden for wrong scope', 'read:collections' + + it 'deletes the collection and returns http success' do + collection + + expect { subject }.to change(Collection, :count).by(-1) + + expect(response).to have_http_status(200) + end + end + end end diff --git a/spec/services/create_collection_service_spec.rb b/spec/services/create_collection_service_spec.rb index 43842c8cc6..bf59e299b1 100644 --- a/spec/services/create_collection_service_spec.rb +++ b/spec/services/create_collection_service_spec.rb @@ -45,7 +45,7 @@ RSpec.describe CreateCollectionService do end context 'when given a tag' do - let(:params) { base_params.merge(tag: '#people') } + let(:params) { base_params.merge(tag_name: '#people') } context 'when the tag exists' do let!(:tag) { Fabricate.create(:tag, name: 'people') } diff --git a/spec/support/threading_helpers.rb b/spec/support/threading_helpers.rb index 4ca8c9865a..cb2a70fb7a 100644 --- a/spec/support/threading_helpers.rb +++ b/spec/support/threading_helpers.rb @@ -6,10 +6,10 @@ module ThreadingHelpers def multi_threaded_execution(thread_count) barrier = Concurrent::CyclicBarrier.new(thread_count) - threads = Array.new(thread_count) do + threads = Array.new(thread_count) do |index| Thread.new do barrier.wait - yield + yield(index) end end diff --git a/yarn.lock b/yarn.lock index c0c3ce0c82..4534183654 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2723,7 +2723,7 @@ __metadata: "@formatjs/intl-pluralrules": "npm:^5.4.4" "@gamestdio/websocket": "npm:^0.3.2" "@github/webauthn-json": "npm:^2.1.1" - "@optimize-lodash/rollup-plugin": "npm:^5.0.2" + "@optimize-lodash/rollup-plugin": "npm:^6.0.0" "@react-spring/web": "npm:^9.7.5" "@reduxjs/toolkit": "npm:^2.0.1" "@storybook/addon-a11y": "npm:^10.0.6" @@ -3027,25 +3027,25 @@ __metadata: languageName: node linkType: hard -"@optimize-lodash/rollup-plugin@npm:^5.0.2": - version: 5.1.0 - resolution: "@optimize-lodash/rollup-plugin@npm:5.1.0" +"@optimize-lodash/rollup-plugin@npm:^6.0.0": + version: 6.0.0 + resolution: "@optimize-lodash/rollup-plugin@npm:6.0.0" dependencies: - "@optimize-lodash/transform": "npm:3.0.6" + "@optimize-lodash/transform": "npm:4.0.0" "@rollup/pluginutils": "npm:^5.1.0" peerDependencies: rollup: ">= 4.x" - checksum: 10c0/cb15712b82164fb63d569caebc278fea4972577009040370b43534edd75069f57974c29e884b3dc59896eda7ed4f28dfcb422c0481d8ea0fe5dfc4546af70774 + checksum: 10c0/2332d642d3e48c5e58618d4b21e77b9b0d723dc8742ca8b49868dd85f931cdce222d0fe3a94948e435888731ed8d33ddc5d1374a200cef074693505c1c66ea15 languageName: node linkType: hard -"@optimize-lodash/transform@npm:3.0.6": - version: 3.0.6 - resolution: "@optimize-lodash/transform@npm:3.0.6" +"@optimize-lodash/transform@npm:4.0.0": + version: 4.0.0 + resolution: "@optimize-lodash/transform@npm:4.0.0" dependencies: estree-walker: "npm:^2.0.2" magic-string: "npm:~0.30.11" - checksum: 10c0/48a877a41e8cb642daccd3a9d815b05c55ac63fc2fdeea6f3e60239e8dcf46a3cd56f6699d67dfd0aebb2e2bb0f019fde6dd7880fb13a7a6db99a53392273578 + checksum: 10c0/8c32212f2ef49103894a75f91958aae43d0498d9db636fb2b7d043d87f241a5a747bff20d0bd5a1595b8704af92cc293806ce00f90836e86c21c1da02672cd48 languageName: node linkType: hard