Merge branch 'develop' into pr/12239

This commit is contained in:
syuilo 2023-11-04 19:52:22 +09:00
commit 8298ebb475
25 changed files with 343 additions and 34 deletions

View File

@ -14,6 +14,9 @@
## 2023.11.0 (unreleased)
### Note
- iOS 16.4未満を使用している場合はiOS 16.4以上にアップデートをお願いします
### General
- Feat: アイコンデコレーション機能
- サーバーで用意された画像をアイコンに重ねることができます
@ -47,6 +50,7 @@
- Enhance: プラグインで`Plugin:register_note_view_interruptor`を用いてnoteの代わりにnullを返却することでートを非表示にできるようになりました
- Enhance: AiScript関数`Mk:nyaize()`が追加されました
- Enhance: 情報→ツール はナビゲーションバーにツールとして独立した項目になりました
- Enhance: ノート内のカスタム絵文字をクリックすることで、コピーおよびリアクションができるように
- Enhance: その他細かなブラッシュアップ
- Fix: 投稿フォームでのユーザー変更がプレビューに反映されない問題を修正
- Fix: ユーザーページの ノート > ファイル付き タブにリプライが表示されてしまう
@ -79,6 +83,7 @@
- Fix: アクセストークンを削除すると、通知が取得できなくなる場合がある問題を修正
- Fix: 自身の宛先なしダイレクト投稿がストリーミングで流れてこない問題を修正
- Fix: サーバーサイドからのテスト通知を正しく行えるように修正
- Fix: GTLの「リートを表示」オプションが機能しないのを修正 #12233
## 2023.10.2

View File

@ -1155,6 +1155,7 @@ refreshing: "Refreshing..."
pullDownToRefresh: "Pull down to refresh"
disableStreamingTimeline: "Disable real-time timeline updates"
useGroupedNotifications: "Display grouped notifications"
signupPendingError: "There was a problem verifying the email address. The link may have expired."
cwNotationRequired: "If \"Hide content\" is enabled, a description must be provided."
_announcement:
forExistingUsers: "Existing users only"
@ -1165,6 +1166,8 @@ _announcement:
tooManyActiveAnnouncementDescription: "Having too many active announcements may worsen the user experience. Please consider archiving announcements that have become obsolete."
readConfirmTitle: "Mark as read?"
readConfirmText: "This will mark the contents of \"{title}\" as read."
shouldNotBeUsedToPresentPermanentInfo: "As it may significantly impact the user experience for new users, it is recommended to use notifications in the flow information rather than stock information."
dialogAnnouncementUxWarn: "Having two or more dialog-style notifications simultaneously can significantly impact the user experience, so please use them carefully."
_initialAccountSetting:
accountCreated: "Your account was successfully created!"
letsStartAccountSetup: "For starters, let's set up your profile."
@ -1177,8 +1180,29 @@ _initialAccountSetting:
pushNotificationDescription: "Enabling push notifications will allow you to receive notifications from {name} directly on your device."
initialAccountSettingCompleted: "Profile setup complete!"
haveFun: "Enjoy {name}!"
youCanContinueTutorial: "You can proceed to a tutorial on how to use {name} (Misskey) or you can exit the setup here and start using it immediately."
startTutorial: "Start Tutorial"
skipAreYouSure: "Really skip profile setup?"
laterAreYouSure: "Really do profile setup later?"
_initialTutorial:
launchTutorial: "Start Tutorial"
title: "Tutorial"
wellDone: "Well done!"
skipAreYouSure: "Quit Tutorial?"
_landing:
title: "Welcome to the Tutorial"
description: "Here, you can learn the basics of using Misskey and its features."
_note:
title: "What is a Note?"
description: "Posts on Misskey are called 'Notes.' Notes are arranged chronologically on the timeline and are updated in real-time."
reply: "Click on this button to reply to a message. It's also possible to reply to replies, continuing the conversation like a thread."
renote: "You can share that note to your own timeline. You can also quote them with your comments."
reaction: "You can add reactions to the Note. More details will be explained on the next page."
menu: "You can view Note details, copy links, and perform various other actions."
_reaction:
title: "What are Reactions?"
description: "Notes can be reacted to with various emojis. Reactions allow you to express nuances that may not be conveyed with just a 'like.'"
letsTryReacting: "Reactions can be added by clicking the '+' button on the note. Try reacting to this sample note!"
_serverRules:
description: "A set of rules to be displayed before registration. Setting a summary of the Terms of Service is recommended."
_serverSettings:

1
locales/index.d.ts vendored
View File

@ -1160,6 +1160,7 @@ export interface Locale {
"useGroupedNotifications": string;
"signupPendingError": string;
"cwNotationRequired": string;
"doReaction": string;
"_announcement": {
"forExistingUsers": string;
"forExistingUsersDescription": string;

View File

@ -590,7 +590,7 @@ invisibleNote: "Nota invisibile"
enableInfiniteScroll: "Abilita scorrimento infinito"
visibility: "Visibilità"
poll: "Sondaggio"
useCw: "Content Warning"
useCw: "Contenuto esplicito"
enablePlayer: "Visualizza"
disablePlayer: "Chiudi"
expandTweet: "Espandi tweet"
@ -808,8 +808,8 @@ user: "Profilo"
administration: "Gestione"
accounts: "Profilo"
switch: "Cambia"
noMaintainerInformationWarning: "Le informazioni amministratore non sono impostate."
noBotProtectionWarning: "Nessuna protezione impostata contro i bot."
noMaintainerInformationWarning: "Mancano le informazioni sull'amministratore."
noBotProtectionWarning: "Non è stata impostata alcuna protezione dai Bot"
configure: "Imposta"
postToGallery: "Pubblicare nella galleria"
postToHashtag: "Pubblica a questo hashtag"
@ -847,7 +847,7 @@ accountDeletionInProgress: "È in corso l'eliminazione del profilo"
usernameInfo: "Un nome per identificare univocamente il tuo profilo sull'istanza. Puoi utilizzare caratteri alfanumerici maiuscoli, minuscoli e il trattino basso (_). Non potrai cambiare nome utente in seguito."
aiChanMode: "Modalità Ai"
devMode: "Modalità sviluppatori"
keepCw: "Mantieni il Content Warning"
keepCw: "Mostra i contenuti espliciti"
pubSub: "Publish/Subscribe del profilo"
lastCommunication: "La comunicazione più recente"
resolved: "Risolto"
@ -1155,6 +1155,8 @@ refreshing: "Aggiornamento..."
pullDownToRefresh: "Trascina per aggiornare"
disableStreamingTimeline: "Disabilitare gli aggiornamenti della TL in tempo reale"
useGroupedNotifications: "Mostra le notifiche raggruppate"
signupPendingError: "Si è verificato un problema durante la verifica del tuo indirizzo email. Potrebbe essere scaduto il collegamento temporaneo."
cwNotationRequired: "Devi indicare perché il contenuto è indicato come esplicito."
_announcement:
forExistingUsers: "Solo ai profili attuali"
forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio."
@ -1164,6 +1166,8 @@ _announcement:
tooManyActiveAnnouncementDescription: "L'esperienza delle persone può peggiorare se ci sono troppi annunci attivi. Considera anche l'archiviazione degli annunci conclusi."
readConfirmTitle: "Segnare come già letto?"
readConfirmText: "Hai già letto \"{title}˝?"
shouldNotBeUsedToPresentPermanentInfo: "Ti consigliamo di utilizzare gli annunci per pubblicare informazioni tempestive e limitate nel tempo, anziché informazioni importanti a lungo andare nel tempo, poiché potrebbero risultare difficili da ritrovare e peggiorare la fruibilità del servizio, specialmente alle nuove persone iscritte."
dialogAnnouncementUxWarn: "Ti consigliamo di usarli con cautela, poiché è molto probabile che avere più di un annuncio in stile \"finestra di dialogo\" peggiori sensibilmente la fruibilità del servizio, specialmente alle nuove persone iscritte."
_initialAccountSetting:
accountCreated: "Il tuo profilo è stato creato!"
letsStartAccountSetup: "Per iniziare, impostiamo il tuo profilo."
@ -1176,8 +1180,77 @@ _initialAccountSetting:
pushNotificationDescription: "Attivare le notifiche push ti permettera di ricevere informazioni sulla attività di {name} direttamente sul tuo dispositivo."
initialAccountSettingCompleted: "Hai completato la configurazione iniziale!"
haveFun: "Divertiti con {name}!"
youCanContinueTutorial: "Puoi continuare con l'esercitazione su come usare {name} (Misskey), oppure interrompere, iniziando subito a usarlo."
startTutorial: "Avvia l'esercitazione"
skipAreYouSure: "Vuoi davvero saltare la configurazione iniziale?"
laterAreYouSure: "Vuoi davvero rimandare la configurazione iniziale?"
_initialTutorial:
launchTutorial: "Guarda il tutorial"
title: "Tutorial"
wellDone: "Ottimo lavoro!"
skipAreYouSure: "Vuoi davvero interrompere il tutorial?"
_landing:
title: "Eccoci nel tutorial"
description: "Qui puoi verificare l'uso delle funzionalità base di Misskey."
_note:
title: "Cosa sono le Note?"
description: "Gli status su Misskey sono chiamati \"Note\". Le Note sono elencate in ordine cronologico nelle timeline e vengono aggiornate in tempo reale."
reply: "Puoi rispondere alle Note. Puoi anche rispondere alle risposte e continuare i dialoghi come un conversazioni."
renote: "Puoi ri-condividere le Note, facendole rifluire sulla Timeline. Puoi anche aggiungere testo e citare altri profili."
reaction: "Puoi aggiungere una reazione. Nella pagina successiva spiegheremo i dettagli."
menu: "Puoi svolgere varie attività, come visualizzare i dettagli delle Note o copiare i collegamenti."
_reaction:
title: "Cosa sono le Reazioni?"
description: "Puoi reagire alle Note. Le sensazioni che non si riescono a trasmettere con i \"Mi piace\" si possono esprimere facilmente inviando una reazione."
letsTryReacting: "Puoi aggiungere una Reazione cliccando il bottone \"+\" (più) della relativa Nota. Prova ad aggiungerne una a questa Nota di esempio!"
reactToContinue: "Aggiungere la Reazione ti consentirà di procedere col tutorial."
reactNotification: "Quando qualcuno reagisce alle tue Note, ricevi una notifica in tempo reale."
reactDone: "Puoi annullare la tua Reazione premendo il bottone \"ー\" (meno)"
_timeline:
title: "Come funziona la Timeline"
description1: "Misskey fornisce alcune Timeline (sequenze cronologiche di Note). Una di queste potrebbe essere stata disattivata dagli amministratori."
home: "Puoi vedere le Note provenienti dai profili che segui (follow)."
local: "Puoi vedere tutte le Note pubblicate dai profili di questa istanza."
social: "Puoi vedere sia le Note della Timeline Home che quelle della Timeline Locale, insieme!"
global: "Puoi vedere le Note da pubblicate da tutte le altre istanze federate con la nostra."
description2: "Nella parte superiore dello schermo, puoi scegliere una Timeline o l'altra in qualsiasi momento."
description3: "Ci sono anche sequenze temporali di elenchi, sequenze temporali di canali, ecc. Per ulteriori dettagli, consultare il {link}.\nPuoi vedere anche Timeline delle liste di profili (se ne hai create), canali, ecc... Per i dettagli, visita {link}."
_postNote:
title: "La Nota e le sue impostazioni"
description1: "Quando scrivi una Nota su Misskey, hai a disposizione varie opzioni. Il modulo di invio è simile a questo."
_visibility:
description: "Puoi limitare chi può vedere la tua Nota."
public: "Visibile a tutti."
home: "Pubblicato solo sulla Timeline Home (personale). Visibile anche da profili remoti follower, visitatori del tuo profilo e tramite i Rinota dei follower."
followers: "Visibile solo ai profili tuoi follower (locali o remoti). Nessun altro oltre a te può \"Rinotare\"."
direct: "Visibile solo ai profili specificati, i quali riceveranno una notifica. Puoi usarlo come se fossero messaggi diretti."
doNotSendConfidencialOnDirect1: "Attenzione, quando si inviano informazioni confidenziali."
doNotSendConfidencialOnDirect2: "Poiché le Note non sono crittografate, l'amministratore del server di destinazione potrebbe leggere cosa è stato scritto, quindi se spedisci una Nota diretta a un profilo che risiede su un server non attendibile, evita di scrivere informazioni riservate."
localOnly: "Indipendentemente dalla visualizzazione sopra indicata, i profili su altri server non saranno in grado di visualizzare la Nota, se questa impostazione è attivata. Non non verrà comunicata ad altri server."
_cw:
title: "Nascondere il contenuto esplicito"
description: "Verrà visualizzato il testo scritto nel campo \"Annotazione preventiva\" al posto del testo principale della Nota. Premere il bottone \"Continua la lettura\" se si intende davvero leggere il testo."
_exampleNote:
cw: "Attenzione: contiene zuccheri"
note: "Ho appena mangiato una ciambella ricoperta di cioccolato 🍩😋"
useCases: "Utilizzalo per chiarire il contenuto della Nota, prima che sia letta. Come richiesto dal regolamento del server o per autoregolamentare spoiler e testi troppo espliciti."
_howToMakeAttachmentsSensitive:
title: "Come indicare che gli allegati sono espliciti?"
description: "Contrassegnare gli allegati come espliciti, va fatto quando è richiesto dal regolamento del server o quando gli allegati non devono essere immediatamente visibili."
tryThisFile: "Prova a rendere esplicite le immagini allegate a questo modulo!"
_exampleNote:
note: "Ho fatto un errore aprendo il coperchio del natto... (fagioli di soia fermentati, particolarmente appiccicosi)"
method: "Per indicare che un allegato è esplicito, tocca il file per aprirne il menu e scegliere la voce \"Segna come esplicito\"."
sensitiveSucceeded: "Quando alleghi file, assicurati di indicare se è materiale esplicito, in modo appropriato, in base al regolamento del tuo server."
doItToContinue: "Impostando l'immagine come esplicita, potrai procedere col tutorial."
_done:
title: "Il tutorial è finito! 🎉"
description: "Queste sono solamente alcune delle funzionalità principali di Misskey. Per ulteriori informazioni, {link}."
_timelineDescription:
home: "Nella Timeline Home, la tua cronologia principale, puoi vedere le Note provenienti dai profili che segui (follow)."
local: "La Timeline Locale, è una cronologia di Note pubblicate da tutti i profili iscritti su questo server."
social: "La Timeline Sociale, unisce in ordine cronologico l'elenco di Note presenti nella Timeline Home e quella Locale."
global: "La Timeline Federata ti consente di vedere le Note pubblicate dai profili di tutti gli altri server federati a questo."
_serverRules:
description: "In Europa è necessario mostrare l'informativa sul trattamento dei dati personali, prima della registrazione al servizio."
_serverSettings:
@ -1447,6 +1520,9 @@ _achievements:
_smashTestNotificationButton:
title: "Prove eccessive"
description: "Hai provato le notifiche consecutivamente in un periodo di tempo molto breve"
_tutorialCompleted:
title: "Attestato di partecipazione al corso per principianti di Misskey"
description: "Ha completato il tutorial"
_role:
new: "Nuovo ruolo"
edit: "Modifica ruolo"
@ -1635,6 +1711,7 @@ _channel:
notesCount: "{n} note"
nameAndDescription: "Nome e descrizione"
nameOnly: "Solo il nome"
allowRenoteToExternal: "Consenti i Rinota e le citazioni all'esterno del canale"
_menuDisplay:
sideFull: "Laterale"
sideIcon: "Laterale (solo icone)"

View File

@ -1157,6 +1157,7 @@ disableStreamingTimeline: "タイムラインのリアルタイム更新を無
useGroupedNotifications: "通知をグルーピングして表示する"
signupPendingError: "メールアドレスの確認中に問題が発生しました。リンクの有効期限が切れている可能性があります。"
cwNotationRequired: "「内容を隠す」がオンの場合は注釈の記述が必要です。"
doReaction: "リアクションする"
_announcement:
forExistingUsers: "既存ユーザーのみ"

View File

@ -531,6 +531,7 @@ serverLogs: "서버 로그"
deleteAll: "모두 삭제"
showFixedPostForm: "타임라인 상단에 글 작성란을 표시"
showFixedPostFormInChannel: "채널 타임라인 상단에 글 작성란을 표시"
withRepliesByDefaultForNewlyFollowed: "팔로우 할 때 기본적으로 답글을 타임라인에 나오게 하기"
newNoteRecived: "새 노트가 있습니다"
sounds: "소리"
sound: "소리"
@ -711,6 +712,7 @@ lockedAccountInfo: "팔로우를 승인으로 승인받더라도 노트의 공
alwaysMarkSensitive: "미디어를 항상 열람 주의로 설정"
loadRawImages: "첨부한 이미지의 썸네일을 원본화질로 표시"
disableShowingAnimatedImages: "움직이는 이미지를 자동으로 재생하지 않음"
highlightSensitiveMedia: "미디어가 민감한 내용이라는 것을 알기 쉽게 표시"
verificationEmailSent: "확인 메일을 발송하였습니다. 설정을 완료하려면 메일에 첨부된 링크를 확인해 주세요."
notSet: "설정되지 않음"
emailVerified: "메일 주소가 확인되었습니다."
@ -1122,8 +1124,26 @@ showRenotes: "리노트 표시"
edited: "수정됨"
notificationRecieveConfig: "알림 설정"
mutualFollow: "맞팔로우"
showRepliesToOthersInTimeline: "타임라인에 다른 사람에게 보내는 답글을 포함"
hideRepliesToOthersInTimeline: "타임라인에 다른 사람에게 보내는 답글을 포함하지 않음"
showRepliesToOthersInTimelineAll: "타임라인에 현재 팔로우 중인 사람 전원의 답글을 포함하게 하기"
hideRepliesToOthersInTimelineAll: "타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하기"
confirmShowRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?"
confirmHideRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?"
externalServices: "외부 서비스"
impressum: "운영자 정보"
impressumUrl: "운영자 정보 URL"
impressumDescription: "독일 등의 일부 나라와 지역에서는 꼭 표시해야 합니다(Impressum)."
avatarDecorations: "아이콘 장식"
attach: "붙이기"
detach: "떼기"
angle: "각도"
flip: "플립"
showAvatarDecorations: "아이콘 장식을 표시"
disableStreamingTimeline: "타임라인의 실시간 갱신을 무효화하기"
useGroupedNotifications: "알림을 그룹화하고 표시"
signupPendingError: "메일 주소 확인중에 문제가 발생했습니다. 링크의 유효기간이 지났을 가능성이 있습니다."
cwNotationRequired: "'내용을 숨기기'를 체크했을 경우 주석을 써야 합니다."
_announcement:
forExistingUsers: "기존 유저에게만 알림"
forExistingUsersDescription: "활성화하면 이 공지사항을 게시한 시점에서 이미 가입한 유저에게만 표시합니다. 비활성화하면 게시 후에 가입한 유저에게도 표시합니다."
@ -1145,8 +1165,22 @@ _initialAccountSetting:
pushNotificationDescription: "푸시 알림을 활성화하면 {name}의 알림을 나의 기기에서 받아볼 수 있게 됩니다."
initialAccountSettingCompleted: "초기 설정을 모두 마쳤습니다!"
haveFun: "{name}와 함께 즐거운 시간 보내세요!"
youCanContinueTutorial: "이대로 {name}(Misskey)의 사용법에 대해 튜토리얼을 진행할 수도 있지만, 여기서 중단하고 바로 시작할 수도 있습니다."
startTutorial: "튜토리얼 시작"
skipAreYouSure: "초기 설정을 중단하시겠습니까?"
laterAreYouSure: "초기 설정을 나중에 진행하시겠습니까?"
_initialTutorial:
launchTutorial: "튜토리얼 보기"
title: "튜토리얼"
wellDone: "잘 하셨습니다"
skipAreYouSure: "튜토리얼을 종료하시겠습니까?"
_landing:
description: "여기서는 미스키의 기본적인 사용법이나 기능을 확인할 수 있습니다."
_note:
description: "미스키에서는 게시물을 '노트'라고 합니다. 노트는 타임라인에 시간순으로 정렬되어 있고, 실시간으로 갱신됩니다."
reply: "답글을 다는 것이 가능합니다. 답글에 답글을 다는 것도 가능하며 스레드처럼 대화를 계속하는 것도 가능합니다."
renote: "그 노트를 자기 타임라인에 가져와서 공유하는 것이 가능합니다. 글을 추가해서 인용하는 것도 가능합니다."
reaction: "리액션을 다는 것이 가능합니다. 다음 페이지에서 자세한 설명을 볼 수 있습니다."
_serverRules:
description: "회원 가입 이전에 간단하게 표시할 서버 규칙입니다. 이용 약관의 요약으로 구성하는 것을 추천합니다."
_serverSettings:

View File

@ -1155,6 +1155,7 @@ refreshing: "載入更新中"
pullDownToRefresh: "往下拉來更新內容"
disableStreamingTimeline: "停用時間軸的即時更新"
useGroupedNotifications: "分組顯示通知訊息"
signupPendingError: "驗證您的電子郵件地址時出現問題。連結可能已過期。"
cwNotationRequired: "如果開啟「隱藏內容」,則需要註解說明。"
_announcement:
forExistingUsers: "僅限既有的使用者"
@ -1165,6 +1166,8 @@ _announcement:
tooManyActiveAnnouncementDescription: "有過多公告可能會影響使用者體驗。請考慮歸檔已結束的公告。"
readConfirmTitle: "標記為已讀嗎?"
readConfirmText: "閱讀「{title}」的內容並標記為已讀。"
shouldNotBeUsedToPresentPermanentInfo: "由於可能會破壞使用者體驗,尤其是對於新使用者而言,我們建議使用公告來發布有時效性的資訊而不是固定不變的資訊。"
dialogAnnouncementUxWarn: "如果同時有 2 個以上對話方塊形式的公告存在,對於使用者體驗很可能會有不良的影響,因此建議謹慎使用。"
_initialAccountSetting:
accountCreated: "帳戶已建立完成!"
letsStartAccountSetup: "來進行帳戶的初始設定吧。"
@ -1177,8 +1180,77 @@ _initialAccountSetting:
pushNotificationDescription: "啟用推送通知,就可以在設備上接收{name}的通知。"
initialAccountSettingCompleted: "初始設定完成了!"
haveFun: "盡情享受{name}吧!"
youCanContinueTutorial: "您可以繼續學習如何使用{name}(Misskey),也可以就此打住,立即開始使用。"
startTutorial: "開始教學課程"
skipAreYouSure: "要略過初始設定嗎?"
laterAreYouSure: "稍後再重新進行初始設定嗎?"
_initialTutorial:
launchTutorial: "觀看教學課程"
title: "新手教學"
wellDone: "做得好"
skipAreYouSure: "結束教學模式?"
_landing:
title: "歡迎使用本教學課程"
description: "在這裡您可以查看Misskey的基本使用方法和功能。"
_note:
title: "什麼是貼文?"
description: "在Misskey上發布的內容稱為「貼文」。貼文在時間軸上按時間順序排列並即時更新。"
reply: "您可以回覆貼文,並像討論串一樣繼續對話。"
renote: "您可以將此貼文分享到自己的時間軸。您也可以在引用時添加文字。"
reaction: "您可以添加反應。詳細資訊將在下一頁進行說明。"
menu: "可執行各種操作,如查看貼文詳細資訊和複製連結。"
_reaction:
title: "什麼是反應?"
description: "您可以在貼文中添加「反應」。您可以使用反應輕鬆隨意地表達「最愛/大心」所無法傳達的細微差別。"
letsTryReacting: "可以透過點擊貼文上的「+」按鈕來添加反應。請嘗試在此範例貼文添加反應!"
reactToContinue: "添加反應以繼續教學課程。"
reactNotification: "當有人對您的貼文做出反應時會即時接收到通知。"
reactDone: "按下「-」按鈕可以取消反應。"
_timeline:
title: "時間軸如何運作"
description1: "Misskey根據使用方式提供了多個時間軸伺服器可能會將部份時間軸停用。"
home: "您可以查看您追隨的使用者的貼文。"
local: "您可以看到此伺服器上所有使用者的貼文。"
social: "來自首頁時間軸和本地時間軸的貼文都會顯示。"
global: "可以看到其他已連接伺服器的貼文。"
description2: "您可以隨時在螢幕上方切換對應的時間軸。"
description3: "除此之外還有清單時間軸、頻道時間軸等。請參閱{link}以了解更多詳情。"
_postNote:
title: "貼文的發布設定"
description1: "在Misskey上發布貼文時可以設定各種選項。發布表單如下所示。"
_visibility:
description: "可以限制誰可以看到您的貼文。"
public: "所有人都可以看見。"
home: "僅在首頁時間軸上發布。其他使用者只在下列情況可看見該貼文:追隨者、觀看使用者的個人資料頁面,以及貼文被轉發時。"
followers: "僅追隨者可見。只有發文者本人可轉發,未追隨發文者的使用者無法看見。"
direct: "僅指定的使用者可見,對方也會收到通知。可代替直接訊息使用。"
doNotSendConfidencialOnDirect1: "發送機密訊息時請務必注意。"
doNotSendConfidencialOnDirect2: "目標伺服器的管理員可以看到發布的內容,因此如果您向不受信任的伺服器上的使用者發送直接訊息,必須小心處理機密訊息。"
localOnly: "不將貼文發布到聯邦上的其他伺服器。不論上述發布範圍,使用此設定後,其他伺服器上的使用者將無法直接查看此貼文。"
_cw:
title: "隱藏內容CW"
description: "將顯示「註釋」中寫入的內容而不是本文。按一下「查看更多」以顯示本文。"
_exampleNote:
cw: "美食恐怖主義注意"
note: "我吃了一個巧克力甜甜圈🍩😋"
useCases: "伺服器的服務條款可能會規範特定的貼文需要使用隱藏內容,除此之外也會用在隱藏劇情洩漏與敏感內容的貼文。"
_howToMakeAttachmentsSensitive:
title: "如何標記上傳附件為敏感內容?"
description: "如果伺服器服務條款有規範,又或者不希望上傳附件直接被看見,可以設置為「敏感內容」"
tryThisFile: "試試看!把附加在發文表單的圖像檔案標記為敏感內容。"
_exampleNote:
note: "打開納豆的包裝失敗了…"
method: "若要使上傳附件標記為敏感內容,請按一下該檔案以開啟選單,然後點擊「標記為敏感內容」。"
sensitiveSucceeded: "上傳附件時,請務必根據伺服器的服務條款適當設定敏感內容。"
doItToContinue: "把圖像標記為敏感內容以繼續教學課程。"
_done:
title: "教學課程已結束"
description: "這裡介紹的功能只是其中的一小部分。要了解更多有關如何使用Misskey的資訊請瀏覽{link}。"
_timelineDescription:
home: "在首頁時間線上,可以看到您追隨的使用者的貼文。"
local: "在本地時間軸上,可以看到此伺服器所有使用者的貼文。"
social: "在社交時間軸上,可以看到首頁與本地時間軸的貼文。"
global: "在公開時間軸上,可以看到其他已連接伺服器的貼文。\n"
_serverRules:
description: "設定在註冊頁面顯示的伺服器簡要規則。建議是服務條款的摘要。"
_serverSettings:
@ -1448,6 +1520,9 @@ _achievements:
_smashTestNotificationButton:
title: "過度測試"
description: "極短時間內連續測試通知"
_tutorialCompleted:
title: "Misskey新手講座 結業證書"
description: "已完成教學課程"
_role:
new: "建立角色"
edit: "編輯角色"
@ -1636,6 +1711,7 @@ _channel:
notesCount: "有 {n} 篇貼文"
nameAndDescription: "名稱與說明"
nameOnly: "僅名稱"
allowRenoteToExternal: "允許在頻道外轉發和引用"
_menuDisplay:
sideFull: "橫向"
sideIcon: "橫向(圖示)"
@ -1865,7 +1941,7 @@ _widgets:
clicker: "點擊器"
_cw:
hide: "隱藏"
show: "瀏覽更多"
show: "顯示內容"
chars: "{count} 個字元"
files: "{count} 個檔案"
_poll:

View File

@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "2023.11.0-beta.9",
"version": "2023.11.0-beta.10",
"codename": "nasubi",
"repository": {
"type": "git",

View File

@ -87,6 +87,16 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (ps.withFiles) {
query.andWhere('note.fileIds != \'{}\'');
}
if (ps.withRenotes === false) {
query.andWhere(new Brackets(qb => {
qb.where('note.renoteId IS NULL');
qb.orWhere(new Brackets(qb => {
qb.where('note.text IS NOT NULL');
qb.orWhere('note.fileIds != \'{}\'');
}));
}));
}
//#endregion
const timeline = await query.limit(ps.limit).getMany();

View File

@ -53,19 +53,28 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
<div style="container-type: inline-size;">
<p v-if="appearNote.cw != null" :class="$style.cw">
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'account'" :i="$i"/>
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'account'"/>
<MkCwButton v-model="showContent" :note="appearNote" style="margin: 4px 0;"/>
</p>
<div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
<div :class="$style.text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<MkA v-if="appearNote.replyId" :class="$style.replyIcon" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
<Mfm v-if="appearNote.text" :parsedNodes="parsed" :text="appearNote.text" :author="appearNote.user" :nyaize="'account'" :i="$i" :emojiUrls="appearNote.emojis"/>
<Mfm
v-if="appearNote.text"
:parsedNodes="parsed"
:text="appearNote.text"
:author="appearNote.user"
:nyaize="'account'"
:emojiUrls="appearNote.emojis"
:enableEmojiMenu="true"
:enableEmojiMenuReaction="true"
/>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else>
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'account'" :i="$i" :emojiUrls="appearNote.emojis"/>
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'account'" :emojiUrls="appearNote.emojis"/>
</div>
</div>
</div>
@ -242,6 +251,13 @@ const keymap = {
's': () => showContent.value !== showContent.value,
};
provide('react', (reaction: string) => {
os.api('notes/reactions/create', {
noteId: appearNote.id,
reaction: reaction,
});
});
if (props.mock) {
watch(() => props.note, (to) => {
note = deepClone(to);

View File

@ -67,19 +67,28 @@ SPDX-License-Identifier: AGPL-3.0-only
</header>
<div :class="$style.noteContent">
<p v-if="appearNote.cw != null" :class="$style.cw">
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'account'" :i="$i"/>
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :nyaize="'account'"/>
<MkCwButton v-model="showContent" :note="appearNote"/>
</p>
<div v-show="appearNote.cw == null || showContent">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<MkA v-if="appearNote.replyId" :class="$style.noteReplyTarget" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
<Mfm v-if="appearNote.text" :parsedNodes="parsed" :text="appearNote.text" :author="appearNote.user" :nyaize="'account'" :i="$i" :emojiUrls="appearNote.emojis"/>
<Mfm
v-if="appearNote.text"
:parsedNodes="parsed"
:text="appearNote.text"
:author="appearNote.user"
:nyaize="'account'"
:emojiUrls="appearNote.emojis"
:enableEmojiMenu="true"
:enableEmojiMenuReaction="true"
/>
<a v-if="appearNote.renote != null" :class="$style.rn">RN:</a>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else>
<b>{{ i18n.t('translatedFrom', { x: translation.sourceLang }) }}: </b>
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'account'" :i="$i" :emojiUrls="appearNote.emojis"/>
<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'account'" :emojiUrls="appearNote.emojis"/>
</div>
</div>
<div v-if="appearNote.files.length > 0">
@ -184,7 +193,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
import { computed, inject, onMounted, ref, shallowRef } from 'vue';
import { computed, inject, onMounted, provide, ref, shallowRef } from 'vue';
import * as mfm from 'mfm-js';
import * as Misskey from 'misskey-js';
import MkNoteSub from '@/components/MkNoteSub.vue';
@ -276,6 +285,13 @@ const keymap = {
's': () => showContent.value !== showContent.value,
};
provide('react', (reaction: string) => {
os.api('notes/reactions/create', {
noteId: appearNote.id,
reaction: reaction,
});
});
let tab = $ref('replies');
let reactionTabType = $ref(null);

View File

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
<p v-if="note.cw != null" :class="$style.cw">
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'account'" :i="$i" :emojiUrls="note.emojis"/>
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'account'" :emojiUrls="note.emojis"/>
<MkCwButton v-model="showContent" :note="note"/>
</p>
<div v-show="note.cw == null || showContent">

View File

@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
<p v-if="note.cw != null" :class="$style.cw">
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'account'" :i="$i"/>
<Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :nyaize="'account'"/>
<MkCwButton v-model="showContent" :note="note"/>
</p>
<div v-show="note.cw == null || showContent">

View File

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deleted }})</span>
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :emojiUrls="note.emojis"/>
<Mfm v-if="note.text" :text="note.text" :author="note.user" :emojiUrls="note.emojis"/>
<MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
</div>
<details v-if="note.files.length > 0">

View File

@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-if="$i && $i.id !== user.id && user.isFollowed" :class="$style.followed">{{ i18n.ts.followsYou }}</span>
<div :class="$style.description">
<div v-if="user.description" :class="$style.mfm">
<Mfm :text="user.description" :author="user" :i="$i"/>
<Mfm :text="user.description" :author="user"/>
</div>
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
</div>

View File

@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.username"><MkAcct :user="user"/></div>
</div>
<div :class="$style.description">
<Mfm v-if="user.description" :class="$style.mfm" :text="user.description" :author="user" :i="$i"/>
<Mfm v-if="user.description" :class="$style.mfm" :text="user.description" :author="user"/>
<div v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</div>
</div>
<div :class="$style.status">

View File

@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<div :class="$style.description">
<div v-if="user.description" :class="$style.mfm">
<Mfm :text="user.description" :author="user" :i="$i"/>
<Mfm :text="user.description" :author="user"/>
</div>
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
</div>

View File

@ -5,14 +5,27 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<span v-if="errored">:{{ customEmojiName }}:</span>
<img v-else :class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]" :src="url" :alt="alt" :title="alt" decoding="async" @error="errored = true" @load="errored = false"/>
<img
v-else
:class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]"
:src="url"
:alt="alt"
:title="alt"
decoding="async"
@error="errored = true"
@load="errored = false"
@click="onClick"
/>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { computed, inject } from 'vue';
import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js';
import { defaultStore } from '@/store.js';
import { customEmojisMap } from '@/custom-emojis.js';
import * as os from '@/os.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import { i18n } from '@/i18n.js';
const props = defineProps<{
name: string;
@ -21,8 +34,12 @@ const props = defineProps<{
host?: string | null;
url?: string;
useOriginalSize?: boolean;
menu?: boolean;
menuReaction?: boolean;
}>();
const react = inject<((name: string) => void) | null>('react', null);
const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substring(1, props.name.length - 1) : props.name).replace('@.', ''));
const isLocal = computed(() => !props.host && (customEmojiName.value.endsWith('@.') || !customEmojiName.value.includes('@')));
@ -55,6 +72,28 @@ const url = computed(() => {
const alt = computed(() => `:${customEmojiName.value}:`);
let errored = $ref(url.value == null);
function onClick(ev: MouseEvent) {
if (props.menu) {
os.popupMenu([{
type: 'label',
text: `:${props.name}:`,
}, {
text: i18n.ts.copy,
icon: 'ti ti-copy',
action: () => {
copyToClipboard(`:${props.name}:`);
os.success();
},
}, ...(props.menuReaction && react ? [{
text: i18n.ts.doReaction,
icon: 'ti ti-plus',
action: () => {
react(`:${props.name}:`);
},
}] : [])], ev.currentTarget ?? ev.target);
}
}
</script>
<style lang="scss" module>

View File

@ -33,12 +33,13 @@ type MfmProps = {
plain?: boolean;
nowrap?: boolean;
author?: Misskey.entities.UserLite;
i?: Misskey.entities.UserLite | null;
isNote?: boolean;
emojiUrls?: string[];
rootScale?: number;
nyaize: boolean | 'account';
parsedNodes?: mfm.MfmNode[] | null;
enableEmojiMenu?: boolean;
enableEmojiMenuReaction?: boolean;
};
// eslint-disable-next-line import/no-default-export
@ -328,6 +329,8 @@ export default function(props: MfmProps) {
normal: props.plain,
host: null,
useOriginalSize: scale >= 2.5,
menu: props.enableEmojiMenu,
menuReaction: props.enableEmojiMenuReaction,
})];
} else {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition

View File

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div class="_gaps">
<Mfm :text="block.text" :isNote="false" :i="$i"/>
<Mfm :text="block.text" :isNote="false"/>
<MkUrlPreview v-for="url in urls" :key="url" :url="url"/>
</div>
</template>

View File

@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.bannerFade"></div>
</div>
<div v-if="channel.description" :class="$style.description">
<Mfm :text="channel.description" :isNote="false" :i="$i"/>
<Mfm :text="channel.description" :isNote="false"/>
</div>
</div>

View File

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div v-if="clip" class="_gaps">
<div class="_panel">
<div v-if="clip.description" :class="$style.description">
<Mfm :text="clip.description" :isNote="false" :i="$i"/>
<Mfm :text="clip.description" :isNote="false"/>
</div>
<MkButton v-if="favorited" v-tooltip="i18n.ts.unfavorite" asLike rounded primary @click="unfavorite()"><i class="ti ti-heart"></i><span v-if="clip.favoritedCount > 0" style="margin-left: 6px;">{{ clip.favoritedCount }}</span></MkButton>
<MkButton v-else v-tooltip="i18n.ts.favorite" asLike rounded @click="favorite()"><i class="ti ti-heart"></i><span v-if="clip.favoritedCount > 0" style="margin-left: 6px;">{{ clip.favoritedCount }}</span></MkButton>

View File

@ -76,7 +76,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div>
<div class="description">
<MkOmit>
<Mfm v-if="user.description" :text="user.description" :isNote="false" :author="user" :i="$i"/>
<Mfm v-if="user.description" :text="user.description" :isNote="false" :author="user"/>
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
</MkOmit>
</div>
@ -100,7 +100,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<Mfm :text="field.name" :plain="true" :colored="false"/>
</dt>
<dd class="value">
<Mfm :text="field.value" :author="user" :i="$i" :colored="false"/>
<Mfm :text="field.value" :author="user" :colored="false"/>
<i v-if="user.verifiedLinks.includes(field.value)" v-tooltip:dialog="i18n.ts.verifiedLink" class="ti ti-circle-check" :class="$style.verifiedLink"></i>
</dd>
</dl>

View File

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div class="_panel" :class="$style.content">
<div>
<MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i"/>
<Mfm v-if="note.text" :text="note.text" :author="note.user"/>
<MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
</div>
<div v-if="note.files.length > 0" :class="$style.richcontent">

View File

@ -3,18 +3,25 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
const enRegex1 = /(?<=n)a/gi;
const enRegex2 = /(?<=morn)ing/gi;
const enRegex3 = /(?<=every)one/gi;
const koRegex1 = /[나-낳]/g;
const koRegex2 = /(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm;
const koRegex3 = /(야(?=\?))|(야$)|(야(?= ))/gm;
export function nyaize(text: string): string {
return text
// ja-JP
.replaceAll('な', 'にゃ').replaceAll('ナ', 'ニャ').replaceAll('ナ', 'ニャ')
// en-US
.replace(/(?<=n)a/gi, x => x === 'A' ? 'YA' : 'ya')
.replace(/(?<=morn)ing/gi, x => x === 'ING' ? 'YAN' : 'yan')
.replace(/(?<=every)one/gi, x => x === 'ONE' ? 'NYAN' : 'nyan')
.replace(enRegex1, x => x === 'A' ? 'YA' : 'ya')
.replace(enRegex2, x => x === 'ING' ? 'YAN' : 'yan')
.replace(enRegex3, x => x === 'ONE' ? 'NYAN' : 'nyan')
// ko-KR
.replace(/[나-낳]/g, match => String.fromCharCode(
.replace(koRegex1, match => String.fromCharCode(
match.charCodeAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0),
))
.replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, '다냥')
.replace(/(야(?=\?))|(야$)|(야(?= ))/gm, '냥');
.replace(koRegex2, '다냥')
.replace(koRegex3, '냥');
}