From 63a244fe1a5d3220702a048afa976addde4f4645 Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 13 Apr 2026 19:28:28 +0200 Subject: [PATCH 1/6] Add `/api/v1_alpha/accounts/:id/in_collections` to list collections you are in (#38657) --- .../api/v1_alpha/in_collections_controller.rb | 63 +++++++++++++++++ app/models/concerns/account/associations.rb | 1 + app/policies/account_policy.rb | 4 ++ config/routes/api.rb | 1 + .../api/v1_alpha/in_collections_spec.rb | 69 +++++++++++++++++++ 5 files changed, 138 insertions(+) create mode 100644 app/controllers/api/v1_alpha/in_collections_controller.rb create mode 100644 spec/requests/api/v1_alpha/in_collections_spec.rb diff --git a/app/controllers/api/v1_alpha/in_collections_controller.rb b/app/controllers/api/v1_alpha/in_collections_controller.rb new file mode 100644 index 0000000000..087464989e --- /dev/null +++ b/app/controllers/api/v1_alpha/in_collections_controller.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +class Api::V1Alpha::InCollectionsController < Api::BaseController + include Authorization + + DEFAULT_COLLECTIONS_LIMIT = 40 + + before_action :check_feature_enabled + + before_action -> { authorize_if_got_token! :read, :'read:collections' }, only: [:index] + + before_action :require_user! + before_action :set_account, only: [:index] + before_action :set_collections, only: [:index] + + after_action :insert_pagination_headers, only: [:index] + + after_action :verify_authorized + + def index + cache_if_unauthenticated! + authorize @account, :index_featured_in_collections? + + render json: @collections, each_serializer: REST::CollectionSerializer, adapter: :json + end + + private + + def set_account + @account = Account.find(params[:account_id]) + end + + def set_collections + @collections = @account.featured_in_collections + .with_tag + .offset(offset_param) + .limit(limit_param(DEFAULT_COLLECTIONS_LIMIT)) + end + + def check_feature_enabled + raise ActionController::RoutingError unless Mastodon::Feature.collections_enabled? + end + + def next_path + return unless records_continue? + + api_v1_alpha_account_in_collections_url(@account, pagination_params(offset: offset_param + limit_param(DEFAULT_COLLECTIONS_LIMIT))) + end + + def prev_path + return if offset_param.zero? + + api_v1_alpha_account_in_collections_url(@account, pagination_params(offset: offset_param - limit_param(DEFAULT_COLLECTIONS_LIMIT))) + end + + def records_continue? + ((offset_param * limit_param(DEFAULT_COLLECTIONS_LIMIT)) + @collections.size) < @account.featured_in_collections.size + end + + def offset_param + params[:offset].to_i + end +end diff --git a/app/models/concerns/account/associations.rb b/app/models/concerns/account/associations.rb index db2e996d0f..8c26a4da64 100644 --- a/app/models/concerns/account/associations.rb +++ b/app/models/concerns/account/associations.rb @@ -18,6 +18,7 @@ module Account::Associations has_many :collections has_many :collection_items has_many :curated_collection_items, through: :collections, class_name: 'CollectionItem', source: :collection_items + has_many :featured_in_collections, through: :collection_items, class_name: 'Collection', source: :collection has_many :conversations, class_name: 'AccountConversation' has_many :custom_filters has_many :favourites diff --git a/app/policies/account_policy.rb b/app/policies/account_policy.rb index c46eb08034..43c1b8c2a3 100644 --- a/app/policies/account_policy.rb +++ b/app/policies/account_policy.rb @@ -72,4 +72,8 @@ class AccountPolicy < ApplicationPolicy def index_collections? current_account.nil? || !record.blocking_or_domain_blocking?(current_account) end + + def index_featured_in_collections? + current_account.id == record.id + end end diff --git a/config/routes/api.rb b/config/routes/api.rb index e1419bebcb..2d2cc80fc8 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -8,6 +8,7 @@ namespace :api, format: false do namespace :v1_alpha do resources :accounts, only: [] do resources :collections, only: [:index] + resources :in_collections, only: [:index] end resources :async_refreshes, only: :show diff --git a/spec/requests/api/v1_alpha/in_collections_spec.rb b/spec/requests/api/v1_alpha/in_collections_spec.rb new file mode 100644 index 0000000000..a4bd3110be --- /dev/null +++ b/spec/requests/api/v1_alpha/in_collections_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe 'Api::V1Alpha::InCollections', feature: :collections do + include_context 'with API authentication', oauth_scopes: 'read:collections write:collections' + + describe 'GET /api/v1_alpha/in_collections' do + subject do + get "/api/v1_alpha/accounts/#{account.id}/in_collections", headers: headers, params: params + end + + let(:params) { {} } + let(:account) { user.account } + + before { Fabricate.times(3, :collection_item, account: account) } + + it 'returns all collections for the given account and http success' do + subject + + expect(response).to have_http_status(200) + expect(response.parsed_body[:collections].size).to eq 3 + end + + context 'with limit param' do + let(:params) { { limit: '1' } } + + it 'returns only a single result' do + subject + + expect(response).to have_http_status(200) + expect(response.parsed_body[:collections].size).to eq 1 + + expect(response) + .to include_pagination_headers( + next: api_v1_alpha_account_in_collections_url(account, limit: 1, offset: 1) + ) + end + end + + context 'with limit and offset params' do + let(:params) { { limit: '1', offset: '1' } } + + it 'returns the correct result and headers' do + subject + + expect(response).to have_http_status(200) + expect(response.parsed_body[:collections].size).to eq 1 + + expect(response) + .to include_pagination_headers( + prev: api_v1_alpha_account_in_collections_url(account, limit: 1, offset: 0), + next: api_v1_alpha_account_in_collections_url(account, limit: 1, offset: 2) + ) + end + end + + context 'when requested account is different from current account' do + let(:account) { Fabricate(:account) } + + it 'returns http forbidden' do + subject + + expect(response) + .to have_http_status(403) + end + end + end +end From 6142c7b003430b92f9c10f66fd48aa646c722e4a Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 14 Apr 2026 11:21:06 +0200 Subject: [PATCH 2/6] Profile redesign: Allow animated and transparent avatars (#38663) --- .../account_edit/modals/image_upload.tsx | 100 +++++++++++++----- 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/app/javascript/mastodon/features/account_edit/modals/image_upload.tsx b/app/javascript/mastodon/features/account_edit/modals/image_upload.tsx index 23636083de..fa8b9df4df 100644 --- a/app/javascript/mastodon/features/account_edit/modals/image_upload.tsx +++ b/app/javascript/mastodon/features/account_edit/modals/image_upload.tsx @@ -64,15 +64,21 @@ export const ImageUploadModal: FC< const [imageBlob, setImageBlob] = useState(null); const handleFile = useCallback((file: File) => { - const reader = new FileReader(); - reader.addEventListener('load', () => { - const result = reader.result; - if (typeof result === 'string' && result.length > 0) { - setImageSrc(result); - setStep('crop'); - } - }); - reader.readAsDataURL(file); + try { + parseImageFile(file, (result, isAnimated) => { + if (isAnimated) { + // If the image is animated, skip cropping and go straight to alt text. + setImageBlob(file); + setStep('alt'); + } else { + setImageSrc(result); + setStep('crop'); + } + }); + } catch (error) { + console.warn('Error with image parsing:', error); + setStep('select'); + } }, []); const handleCrop = useCallback( @@ -104,19 +110,20 @@ export const ImageUploadModal: FC< ); const handleCancel = useCallback(() => { - switch (step) { - case 'crop': - setImageSrc(null); - setStep('select'); - break; - case 'alt': - setImageBlob(null); + if (step === 'crop') { + setImageSrc(null); + setStep('select'); + } else if (step === 'alt') { + setImageBlob(null); + if (imageSrc) { setStep('crop'); - break; - default: - onClose(); + } else { + setStep('select'); + } + } else { + onClose(); } - }, [onClose, step]); + }, [imageSrc, onClose, step]); return ( void, +): void { + const reader = new FileReader(); + reader.onload = () => { + const buffer = reader.result; + if (!(buffer instanceof ArrayBuffer)) { + throw new Error('Expected an ArrayBuffer'); + } + + // Convert the ArrayBuffer to a base64 data URI. + const bytes = new Uint8Array(buffer); + const base64 = btoa(String.fromCharCode(...bytes)); + const dataUri = `data:${file.type};base64,${base64}`; + + // If the file type is not a GIF, then it's not animated as we don't support animated WebP or PNG. + if (file.type !== 'image/gif') { + cb(dataUri, false); + } + + const view = new DataView(buffer, 10); // Start from the last 4 bytes of the Logical Screen Descriptor. + let offset = 3; + + // Check the first bit for the global color table flag. + const globalColorTable = view.getInt8(0); + if (globalColorTable & 0x08) { + // Grab last three bits to calculate the global color table size, and skip it. + offset += 3 * Math.pow(2, (globalColorTable & 0x7) + 1); + } + + // Check Graphics Control Extension and Graphics Control Label to access animated data. + let delayTime = 0; + if (view.getUint8(offset) & 0x21 && view.getUint8(offset + 1) & 0xf9) { + // Skip to the delay time, which is stored in the next two bytes. + delayTime = view.getUint16(offset + 4); + } + + // If there is a delay time, the GIF is animated. + cb(dataUri, delayTime > 0); + }; + reader.readAsArrayBuffer(file); +} + async function calculateCroppedImage( imageSrc: string, crop: Area, @@ -427,10 +482,7 @@ async function calculateCroppedImage( crop.height, ); - return canvas.convertToBlob({ - quality: 0.7, - type: 'image/jpeg', - }); + return canvas.convertToBlob(); } function dataUriToImage(dataUri: string) { From 4fcab304e37ca7575dcbb22e3d6232dcbc20beec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:12:20 +0200 Subject: [PATCH 3/6] New Crowdin Translations (automated) (#38665) Co-authored-by: GitHub Actions --- app/javascript/mastodon/locales/be.json | 2 ++ app/javascript/mastodon/locales/da.json | 2 ++ app/javascript/mastodon/locales/de.json | 2 ++ app/javascript/mastodon/locales/el.json | 2 ++ app/javascript/mastodon/locales/es-AR.json | 2 ++ app/javascript/mastodon/locales/es-MX.json | 2 ++ app/javascript/mastodon/locales/es.json | 2 ++ app/javascript/mastodon/locales/fi.json | 2 ++ app/javascript/mastodon/locales/is.json | 2 ++ app/javascript/mastodon/locales/it.json | 2 ++ app/javascript/mastodon/locales/ja.json | 17 ++++++++++++++++- app/javascript/mastodon/locales/nan-TW.json | 14 ++++++++++++++ app/javascript/mastodon/locales/nl.json | 4 +++- app/javascript/mastodon/locales/sq.json | 2 ++ app/javascript/mastodon/locales/zh-CN.json | 2 ++ app/javascript/mastodon/locales/zh-TW.json | 2 ++ config/locales/simple_form.de.yml | 8 ++++---- config/locales/simple_form.es-AR.yml | 2 +- 18 files changed, 64 insertions(+), 7 deletions(-) diff --git a/app/javascript/mastodon/locales/be.json b/app/javascript/mastodon/locales/be.json index da7eb392a4..988fa26aab 100644 --- a/app/javascript/mastodon/locales/be.json +++ b/app/javascript/mastodon/locales/be.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Вас уключылі ў гэтую калекцыю", "collections.edit_details": "Рэдагаваць падрабязнасці", "collections.error_loading_collections": "Адбылася памылка падчас загрузкі Вашых калекцый.", + "collections.hidden_accounts_description": "Вы заблакіравалі або ігнаруеце {count, plural, one {гэтага карыстальніка} other {гэтых карыстальнікаў}}", + "collections.hidden_accounts_link": "{count, plural, one {# схаваны ўліковы запіс} few {# схаваныя ўліковыя запісы} other {# схаваных уліковых запісаў}}", "collections.hints.accounts_counter": "{count} / {max} уліковых запісаў", "collections.last_updated_at": "Апошняе абнаўленне: {date}", "collections.manage_accounts": "Кіраванне ўліковымі запісамі", diff --git a/app/javascript/mastodon/locales/da.json b/app/javascript/mastodon/locales/da.json index 0161fe2598..cd31aab185 100644 --- a/app/javascript/mastodon/locales/da.json +++ b/app/javascript/mastodon/locales/da.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Du er med i denne samling", "collections.edit_details": "Rediger detaljer", "collections.error_loading_collections": "Der opstod en fejl under indlæsning af dine samlinger.", + "collections.hidden_accounts_description": "Du har blokeret eller skjult {count, plural, one {denne bruger} other {disse brugere}}", + "collections.hidden_accounts_link": "{count, plural, one {# skjult konto} other {# skjulte konti}}", "collections.hints.accounts_counter": "{count} / {max} konti", "collections.last_updated_at": "Senest opdateret: {date}", "collections.manage_accounts": "Administrer konti", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index 48372e3223..b18bde4513 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Du bist ein Teil dieser Sammlung", "collections.edit_details": "Details bearbeiten", "collections.error_loading_collections": "Beim Laden deiner Sammlungen ist ein Fehler aufgetreten.", + "collections.hidden_accounts_description": "Du hast {count, plural, one {dieses Profil} other {diese Profile}} blockiert oder stummgeschaltet", + "collections.hidden_accounts_link": "{count, plural, one {# Konto ausgeblendet} other {# Konten ausgeblendet}}", "collections.hints.accounts_counter": "{count}/{max} Konten", "collections.last_updated_at": "Aktualisiert: {date}", "collections.manage_accounts": "Profile verwalten", diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index b5f1b748f7..6ddda10020 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Είστε αναδεδειγμένοι σε αυτήν τη συλλογή", "collections.edit_details": "Επεξεργασία λεπτομερειών", "collections.error_loading_collections": "Παρουσιάστηκε σφάλμα κατά την προσπάθεια φόρτωσης των συλλογών σας.", + "collections.hidden_accounts_description": "Έχετε αποκλείσει ή κάνει σίγαση {count, plural, one {αυτόν τον χρήστη} other {αυτούς τους χρήστες}}", + "collections.hidden_accounts_link": "{count, plural, one {# κρυμμένος λογαριασμός} other {# κρυμμένοι λογαριασμοί}}", "collections.hints.accounts_counter": "{count} / {max} λογαριασμοί", "collections.last_updated_at": "Τελευταία ενημέρωση: {date}", "collections.manage_accounts": "Διαχείριση λογαριασμών", diff --git a/app/javascript/mastodon/locales/es-AR.json b/app/javascript/mastodon/locales/es-AR.json index 7e1b3f03b8..2e97fe1fce 100644 --- a/app/javascript/mastodon/locales/es-AR.json +++ b/app/javascript/mastodon/locales/es-AR.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Te destacaron en esta colección", "collections.edit_details": "Editar detalles", "collections.error_loading_collections": "Hubo un error al intentar cargar tus colecciones.", + "collections.hidden_accounts_description": "Bloqueaste o silenciaste a {count, plural, one {este usuario} other {estos usuarios}}", + "collections.hidden_accounts_link": "{count, plural, one {# cuenta oculta} other {# cuentas ocultas}}", "collections.hints.accounts_counter": "{count} / {max} cuentas", "collections.last_updated_at": "Última actualización: {date}", "collections.manage_accounts": "Administrar cuentas", diff --git a/app/javascript/mastodon/locales/es-MX.json b/app/javascript/mastodon/locales/es-MX.json index 0ad3aa2ce3..5b97ffa5e3 100644 --- a/app/javascript/mastodon/locales/es-MX.json +++ b/app/javascript/mastodon/locales/es-MX.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Apareces en esta colección", "collections.edit_details": "Editar detalles", "collections.error_loading_collections": "Se produjo un error al intentar cargar tus colecciones.", + "collections.hidden_accounts_description": "Has bloqueado o silenciado {count, plural, one {a este usuario} other {a estos usuarios}}", + "collections.hidden_accounts_link": "{count, plural, one {# cuenta oculta} other {# cuentas ocultas}}", "collections.hints.accounts_counter": "{count} / {max} cuentas", "collections.last_updated_at": "Última actualización: {date}", "collections.manage_accounts": "Administrar cuentas", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 7f891eac40..d2f49929b7 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Apareces en esta colección", "collections.edit_details": "Editar detalles", "collections.error_loading_collections": "Se ha producido un error al intentar cargar tus colecciones.", + "collections.hidden_accounts_description": "Has bloqueado o silenciado {count, plural,one {a este usuario}other {a estos usuarios}}", + "collections.hidden_accounts_link": "{count, plural, one {# cuenta oculta} other {# cuentas ocultas}}", "collections.hints.accounts_counter": "{count} / {max} cuentas", "collections.last_updated_at": "Última actualización: {date}", "collections.manage_accounts": "Administrar cuentas", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 0c1178aac4..5e6dfd6346 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Esiinnyt tässä kokoelmassa", "collections.edit_details": "Muokkaa tietoja", "collections.error_loading_collections": "Kokoelmien latauksessa tapahtui virhe.", + "collections.hidden_accounts_description": "Olet estänyt tai mykistänyt {count, plural, one {tämän käyttäjän} other {nämä käyttäjät}}", + "collections.hidden_accounts_link": "{count, plural, one {# piilotettu tili} other {# piilotettua tiliä}}", "collections.hints.accounts_counter": "{count} / {max} tiliä", "collections.last_updated_at": "Päivitetty viimeksi {date}", "collections.manage_accounts": "Hallitse tilejä", diff --git a/app/javascript/mastodon/locales/is.json b/app/javascript/mastodon/locales/is.json index 0474ed2759..ca3e87d19d 100644 --- a/app/javascript/mastodon/locales/is.json +++ b/app/javascript/mastodon/locales/is.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Þú kemur fyrir í þessu safni", "collections.edit_details": "Breyta ítarupplýsingum", "collections.error_loading_collections": "Villa kom upp þegar reynt var að hlaða inn söfnunum þínum.", + "collections.hidden_accounts_description": "Þú hefur lokað á eða þaggað niður í {count, plural, one {þessum notanda} other {þessum notendum}}", + "collections.hidden_accounts_link": "{count, plural, one {# falinn aðgangur} other {# faldir aðgangar}}", "collections.hints.accounts_counter": "{count} / {max} aðgangar", "collections.last_updated_at": "Síðast uppfært: {date}", "collections.manage_accounts": "Sýsla með notandaaðganga", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index 0aabdbc51d..ea4147cb57 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Sei presente in questa collezione", "collections.edit_details": "Modifica i dettagli", "collections.error_loading_collections": "Si è verificato un errore durante il tentativo di caricare le tue collezioni.", + "collections.hidden_accounts_description": "Hai bloccato o silenziato {count, plural, one {questo utente} other {questi utenti}}", + "collections.hidden_accounts_link": "{count, plural, one {# account nascosto} other {# account nascosti}}", "collections.hints.accounts_counter": "{count} / {max} account", "collections.last_updated_at": "Ultimo aggiornamento: {date}", "collections.manage_accounts": "Gestisci account", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index 34e2253181..ac63875904 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -194,27 +194,41 @@ "collections.accounts.empty_description": "フォローしている {count} アカウントまで追加できます", "collections.accounts.empty_title": "このコレクションは空です", "collections.by_account": "{account_handle} による", + "collections.collection_description": "詳細", "collections.collection_language": "言語", + "collections.collection_name": "名前", + "collections.collection_topic": "トピック", "collections.confirm_account_removal": "このコレクションからこのアカウントを削除してもよろしいですか?", + "collections.content_warning": "閲覧注意", "collections.continue": "次に進む", "collections.create.accounts_subtitle": "あなたがフォローしていてディスカバリー機能にオプトインしたアカウントのみを追加することができます。", "collections.create.accounts_title": "このコレクションで誰に注目しますか?", + "collections.create.basic_details_title": "基本情報", "collections.create.steps": "ステップ {step}/{total}", "collections.create_a_collection_hint": "お気に入りのアカウントを他の人に勧めたり共有するコレクションを作成しましょう。", "collections.create_collection": "コレクションを作成", "collections.delete_collection": "コレクションを削除", - "collections.description_length_hint": "100 文字制限", + "collections.description_length_hint": "100 文字まで", "collections.detail.accounts_heading": "アカウント", "collections.detail.author_added_you_on_date": "{author} があなたを {date} に追加しました", "collections.detail.loading": "コレクションを読み込み中…", "collections.detail.share": "コレクションを共有", "collections.detail.you_are_in_this_collection": "あなたはこのコレクションで紹介されています", "collections.hints.accounts_counter": "{count} / {max} アカウント", + "collections.mark_as_sensitive": "閲覧注意としてマーク", + "collections.mark_as_sensitive_hint": "コレクションの説明とアカウントを閲覧注意で隠します。コレクション名は表示されます。", + "collections.name_length_hint": "40 文字まで", "collections.new_collection": "新規のコレクション", "collections.no_collections_yet": "コレクションはまだありません。", "collections.remove_account": "このアカウントを削除する", "collections.report_collection": "このコレクションを通報する", "collections.search_accounts_label": "追加するアカウントを探す…", + "collections.topic_hint": "ハッシュタグを追加して、このコレクションの主なトピックを知ってもらいましょう。", + "collections.visibility_public": "公開", + "collections.visibility_public_hint": "検索結果やその他おすすめに表示されて、見つけてもらうことができます。", + "collections.visibility_title": "公開範囲", + "collections.visibility_unlisted": "ひかえめな公開", + "collections.visibility_unlisted_hint": "リンクを知っている人が見られます。検索結果やその他おすすめには表示さません。", "column.about": "概要", "column.blocks": "ブロックしたユーザー", "column.bookmarks": "ブックマーク", @@ -461,6 +475,7 @@ "footer.source_code": "ソースコードを表示", "footer.status": "ステータス", "footer.terms_of_service": "サービス利用規約", + "form_field.optional": "(省略可能)", "generic.saved": "保存しました", "getting_started.heading": "スタート", "hashtag.admin_moderation": "#{name}のモデレーション画面を開く", diff --git a/app/javascript/mastodon/locales/nan-TW.json b/app/javascript/mastodon/locales/nan-TW.json index 4d4328da3f..76f25126be 100644 --- a/app/javascript/mastodon/locales/nan-TW.json +++ b/app/javascript/mastodon/locales/nan-TW.json @@ -45,6 +45,7 @@ "account.featured": "精選ê", "account.featured.accounts": "個人資料", "account.featured.collections": "收藏", + "account.featured.new_collection": "新ê收藏", "account.field_overflow": "展示規篇內容", "account.filters.all": "逐ē活動", "account.filters.boosts_toggle": "顯示轉PO", @@ -102,6 +103,7 @@ "account.muted": "消音ah", "account.muting": "消音", "account.mutual": "Lín sio跟tuè", + "account.name.copy": "Khóo-pih口座ê名", "account.name.help.domain": "", "account.name.help.domain_self": "{domain} 是管理lí ê個人資料hām PO文ê服侍器。", "account.name.help.footer": "Tiō親像lí通用別款電子phue程式寄電子phue予別lâng,lí ē當佇別ê Mastodon服侍器hām別lâng交流,koh ē當hām用kap Mastodon kâng款規則(ActivityPub 協定)ê別款社里軟體ê lâng交流。", @@ -138,6 +140,9 @@ "account.unmute": "取消消音 @{name}", "account.unmute_notifications_short": "Kā通知取消消音", "account.unmute_short": "取消消音", + "account_edit.advanced_settings.bot_hint": "Kā別lâng講tsit ê口座主要行自動操作,可能無lâng監控", + "account_edit.advanced_settings.bot_label": "機器lâng ê口座", + "account_edit.advanced_settings.title": "進一步ê設定", "account_edit.bio.add_label": "加添個人紹介", "account_edit.bio.edit_label": "編個人紹介", "account_edit.bio.placeholder": "加一段短紹介,幫tsān別lâng認捌lí。", @@ -346,6 +351,7 @@ "closed_registrations_modal.find_another_server": "Tshuē別ê服侍器", "closed_registrations_modal.preamble": "因為Mastodon非中心化,所以bô論tī tá tsi̍t ê服侍器建立口座,lí lóng ē當跟tuè tsi̍t ê服侍器ê逐ê lâng,kap hām in交流。Lí iā ē當ka-tī起tsi̍t ê站!", "closed_registrations_modal.title": "註冊 Mastodon ê口座", + "collection.share_modal.share_link_label": "分享連結", "collection.share_modal.share_via_post": "PO佇Mastodon頂", "collection.share_modal.share_via_system": "分享kàu……", "collection.share_modal.title": "分享收藏", @@ -426,7 +432,9 @@ "column.list_members": "管理列單ê成員", "column.lists": "列單", "column.mutes": "消音ê用者", + "column.my_collections": "我ê收藏", "column.notifications": "通知", + "column.other_collections": "{name} ê收藏", "column.pins": "釘起來ê PO文", "column.public": "聯邦ê時間線", "column_back_button.label": "頂頁", @@ -496,6 +504,10 @@ "confirmations.follow_to_list.confirm": "跟tuè,加入kàu列單", "confirmations.follow_to_list.message": "Beh kā {name} 加添kàu列單,lí tio̍h先跟tuè伊。", "confirmations.follow_to_list.title": "Kám beh跟tuè tsit ê用者?", + "confirmations.hide_featured_tab.confirm": "Khàm掉分頁", + "confirmations.hide_featured_tab.intro": "Lí不管時ē當佇編輯個人資料→個人資料分頁設定下kha改tse。", + "confirmations.hide_featured_tab.message": "Tse ē kā佇 {serverName} kap別ê pháng上新版本ê Mastodon ê服侍器ê用者khàm掉分頁。其他界面ê顯示可能無kâng款。", + "confirmations.hide_featured_tab.title": "敢beh khàm掉「精選ê」分頁?", "confirmations.logout.confirm": "登出", "confirmations.logout.message": "Lí kám確定beh登出?", "confirmations.logout.title": "Lí kám beh登出?", @@ -575,7 +587,9 @@ "domain_pill.your_server": "Lí數位ê厝,內底有lí所有ê PO文。無kah意?Ē當轉kàu別ê服侍器,koh保有跟tuè lí êl âng。.", "domain_pill.your_username": "Lí 佇tsit ê服侍器獨一ê稱呼。佇無kâng ê服侍器有可能tshuē著kāng名ê用者。", "dropdown.empty": "揀選項", + "email_subscriptions.email": "電子phue箱", "email_subscriptions.form.action": "訂", + "email_subscriptions.form.bottom": "無開Mastodon ê口座,mā ē當佇收件箱收著PO文。不管時lóng ē當取消訂。其他資訊,請參考隱私權政策。", "email_subscriptions.form.title": "訂 {name} ê電子phue更新", "email_subscriptions.submitted.lead": "請檢查lí ê收件箱來完成訂電子批ê更新。", "email_subscriptions.submitted.title": "上尾步", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index a15674072d..bf048403c4 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -85,7 +85,7 @@ "account.menu.copy": "Link kopiëren", "account.menu.direct": "Privébericht", "account.menu.hide_reblogs": "Boosts op tijdlijn verbergen", - "account.menu.mention": "Vermelding", + "account.menu.mention": "Vermelden", "account.menu.mute": "Account negeren", "account.menu.note.description": "Alleen voor jou zichtbaar", "account.menu.open_original_page": "Op {domain} bekijken", @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "Je wordt in deze verzameling uitgelicht", "collections.edit_details": "Gegevens bewerken", "collections.error_loading_collections": "Er is een fout opgetreden bij het laden van je verzamelingen.", + "collections.hidden_accounts_description": "Je hebt {count, plural, one {deze gebruiker} other {deze gebruikers}} geblokkeerd", + "collections.hidden_accounts_link": "{count, plural, one {# verborgen account} other {# verborgen accounts}}", "collections.hints.accounts_counter": "{count} / {max} accounts", "collections.last_updated_at": "Laatst bijgewerkt: {date}", "collections.manage_accounts": "Accounts beheren", diff --git a/app/javascript/mastodon/locales/sq.json b/app/javascript/mastodon/locales/sq.json index bae6d22818..2ec73d415a 100644 --- a/app/javascript/mastodon/locales/sq.json +++ b/app/javascript/mastodon/locales/sq.json @@ -383,6 +383,8 @@ "collections.detail.you_are_in_this_collection": "Shfaqeni te ky koleksion", "collections.edit_details": "Përpunoni hollësi", "collections.error_loading_collections": "Pati një gabim teksa provohej të ngarkoheshin koleksionet tuaj.", + "collections.hidden_accounts_description": "Bllokuat, ose heshtuat {count, plural, one {këtë përdorues} other {këta përdorues}}", + "collections.hidden_accounts_link": "{count, plural, one {# llogari e fshehur} other {# llogari të fshehura}}", "collections.hints.accounts_counter": "{count} / {max} llogari", "collections.last_updated_at": "Përditësuar së fundi më: {date}", "collections.manage_accounts": "Administroni llogari", diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index c5e7764908..2e7b3f46c3 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "你被添加到了此收藏列表", "collections.edit_details": "编辑详情", "collections.error_loading_collections": "加载你的收藏列表时发生错误。", + "collections.hidden_accounts_description": "你已屏蔽或隐藏{count, plural, other {部分用户}}", + "collections.hidden_accounts_link": "{count, plural, other {# 个隐藏账号}}", "collections.hints.accounts_counter": "{count} / {max} 个账号", "collections.last_updated_at": "最后更新:{date}", "collections.manage_accounts": "管理账户", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 677b2fab7e..f236c48f34 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -388,6 +388,8 @@ "collections.detail.you_are_in_this_collection": "您已被加入至此收藏名單", "collections.edit_details": "編輯詳細資料", "collections.error_loading_collections": "讀取您的收藏名單時發生錯誤。", + "collections.hidden_accounts_description": "您已封鎖或靜音{count, plural, other {這些使用者}}", + "collections.hidden_accounts_link": "{count, plural, other {# 個隱藏帳號}}", "collections.hints.accounts_counter": "{count} / {max} 個帳號", "collections.last_updated_at": "最後更新:{date}", "collections.manage_accounts": "管理帳號", diff --git a/config/locales/simple_form.de.yml b/config/locales/simple_form.de.yml index a6bcd6e3c3..049ee60f7d 100644 --- a/config/locales/simple_form.de.yml +++ b/config/locales/simple_form.de.yml @@ -337,13 +337,13 @@ de: notification_emails: appeal: Jemand hat Einspruch gegen eine Maßnahme erhoben digest: Zusammenfassung senden - favourite: wenn jemand meinen Beitrag favorisiert + favourite: Jemand favorisierte meinen Beitrag follow: Ein neues Profil folgt mir - follow_request: Ein Profil fragt an, mir zu folgen - mention: Ich wurde erwähnt + follow_request: Jemand möchte mir folgen + mention: Jemand erwähnte mich pending_account: Ein neues Konto muss überprüft werden quote: Jemand zitierte meinen Beitrag - reblog: wenn jemand meinen Beitrag teilt + reblog: Jemand teilte meinen Beitrag report: Eine neue Meldung wurde eingereicht software_updates: all: Über alle Updates informieren diff --git a/config/locales/simple_form.es-AR.yml b/config/locales/simple_form.es-AR.yml index 6edfae6991..6c616ad244 100644 --- a/config/locales/simple_form.es-AR.yml +++ b/config/locales/simple_form.es-AR.yml @@ -4,7 +4,7 @@ es-AR: hints: account: attribution_domains: Uno por línea. Protege de falsas atribuciones. - discoverable: Puede que aparezcas en colecciones creadas por otros usuarios. También pueden sugerirse tu perfil y publicaciones públicas a otros usuarios en otras funciones de descubrimiento de Mastodon. + discoverable: Puede que aparezcas en colecciones creadas por otros usuarios. También pueden sugerirse tu perfil y publicaciones a otros usuarios en otras funciones de descubrimiento de Mastodon. display_name: Tu nombre completo o tu pseudónimo. fields: Tu sitio web, pronombres, edad, o lo que quieras. indexable: Tus mensajes públicos pueden aparecer en los resultados de la búsqueda en Mastodon. La gente que interactuó con tus mensajes puede ser capaz de buscarlos sin importar el momento. From ba0b9e8ea5d5f161cdecccb3a13caba0a888efc5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 14 Apr 2026 13:28:15 +0200 Subject: [PATCH 4/6] Add publiccode.yml (#38659) --- publiccode.yml | 191 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 publiccode.yml diff --git a/publiccode.yml b/publiccode.yml new file mode 100644 index 0000000000..079e1417a6 --- /dev/null +++ b/publiccode.yml @@ -0,0 +1,191 @@ +publiccodeYmlVersion: 0.5.0 +name: Mastodon +url: https://github.com/mastodon/mastodon +landingURL: https://joinmastodon.org +softwareVersion: v4.5.8 +releaseDate: 2026-03-24 +logo: app/javascript/images/logo.svg +platforms: + - linux + - windows + - web + - mac + - ios + - android +categories: + - communications + - marketing + - online-community + - social-media-management +organisation: + uri: https://joinmastodon.org + name: Mastodon GmbH +usedBy: + - European Commission + - German Federal Government + - Dutch Government +roadmap: https://joinmastodon.org/roadmap +developmentStatus: stable +softwareType: standalone/backend +intendedAudience: + countries: + - AT + - BE + - BG + - CY + - CZ + - DE + - DK + - EE + - ES + - FI + - FR + - GR + - HR + - HU + - IE + - IT + - LT + - LU + - LV + - MT + - NL + - PL + - PT + - RO + - SE + - SI + - SK + scope: + - society + - government + - education + - culture +description: + en: + localisedName: Mastodon + shortDescription: Connecting the world through thriving online communities + longDescription: + 'Mastodon is a free, open-source social network server based on + ActivityPub where users can follow friends and discover new ones. On + Mastodon, users can publish anything they want: links, pictures, text, and + video. All Mastodon servers are interoperable as a federated network + (users on one server can seamlessly communicate with users from another + one, including non-Mastodon software that implements ActivityPub!)' + documentation: https://docs.joinmastodon.org + features: + - Microblogging + - Multimedia (Images, Video, Audio) + - Polls + - Public profiles + - RSS feeds + - User roles and permissions + - Two factor authentication +legal: + license: AGPL-3.0-or-later +maintenance: + type: internal + contacts: + - name: Eugen Rochko + email: eugen@joinmastodon.org + affiliation: Mastodon GmbH +localisation: + localisationReady: true + availableLanguages: + - af + - an + - ar + - ast + - be + - bg + - bn + - br + - bs + - ca + - ckb + - co + - cs + - cy + - da + - de + - el + - en + - en-GB + - eo + - es + - es-AR + - es-MX + - et + - eu + - fa + - fi + - fo + - fr + - fr-CA + - fy + - ga + - gd + - gl + - he + - hi + - hr + - hu + - hy + - ia + - id + - ie + - ig + - io + - is + - it + - ja + - ka + - kab + - kk + - kn + - ko + - ku + - kw + - la + - lt + - lv + - mk + - ml + - mr + - ms + - my + - nan-TW + - nl + - nn + - 'no' + - oc + - pa + - pl + - pt-BR + - pt-PT + - ro + - ru + - sa + - sc + - sco + - si + - sk + - sl + - sq + - sr + - sr-Latn + - sv + - szl + - ta + - te + - th + - tr + - tt + - ug + - uk + - ur + - vi + - zgh + - zh-CN + - zh-HK + - zh-TW From d931e2f30d107899a8392744358a508962a7222b Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 14 Apr 2026 13:58:50 +0200 Subject: [PATCH 5/6] Prevents featured tags from flickering (#38667) --- .../mastodon/features/account_timeline/v2/styles.module.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/mastodon/features/account_timeline/v2/styles.module.scss b/app/javascript/mastodon/features/account_timeline/v2/styles.module.scss index f7dee496fb..cd5cef3f29 100644 --- a/app/javascript/mastodon/features/account_timeline/v2/styles.module.scss +++ b/app/javascript/mastodon/features/account_timeline/v2/styles.module.scss @@ -67,6 +67,10 @@ flex-wrap: nowrap; overflow: hidden; position: relative; + + > button { + flex-shrink: 0; + } } .tagsListShowAll { From 2b93d19d2ca18366b015e3dcde412e67625fe8f5 Mon Sep 17 00:00:00 2001 From: Claire Date: Tue, 14 Apr 2026 15:15:59 +0200 Subject: [PATCH 6/6] Update handle explainer copy (#38646) Co-authored-by: nicolas --- .../features/account_timeline/components/account_name.tsx | 2 +- app/javascript/mastodon/locales/en.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/features/account_timeline/components/account_name.tsx b/app/javascript/mastodon/features/account_timeline/components/account_name.tsx index ff10d82ad7..a1d646ac8b 100644 --- a/app/javascript/mastodon/features/account_timeline/components/account_name.tsx +++ b/app/javascript/mastodon/features/account_timeline/components/account_name.tsx @@ -189,7 +189,7 @@ const AccountNameHelp: FC<{ diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index b67304cbb4..76bf0fba87 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -106,7 +106,7 @@ "account.name.copy": "Copy handle", "account.name.help.domain": "{domain} is the server that hosts the user’s profile and posts.", "account.name.help.domain_self": "{domain} is your server that hosts your profile and posts.", - "account.name.help.footer": "Just like you can send emails to people using different email clients, you can interact with people on other Mastodon servers – and with anyone on other social apps powered by the same set of rules as Mastodon uses (the ActivityPub protocol).", + "account.name.help.footer": "Just like you can send emails to people using different email providers, you can interact with people on other Mastodon servers, and with anyone on other Mastodon-compatible social apps.", "account.name.help.header": "A handle is like an email address", "account.name.help.username": "{username} is this account’s username on their server. Someone on another server might have the same username.", "account.name.help.username_self": "{username} is your username on this server. Someone on another server might have the same username.",