Compare commits

..

No commits in common. "c96f345f01d2a13f762d22414a00a39d6a69c927" and "b0c0d1b294671a37de2cff1b83a0ff5e7c25c770" have entirely different histories.

23 changed files with 455 additions and 325 deletions

View File

@ -1342,7 +1342,6 @@ bottom: "A baix "
top: "A dalt " top: "A dalt "
embed: "Incrustar" embed: "Incrustar"
settingsMigrating: "Estem fent la migració de la teva configuració. Si us plau espera un moment... (També pots fer la migració més tard i manualment anant a Preferències → Altres configuracions → Migrar configuració antiga)" settingsMigrating: "Estem fent la migració de la teva configuració. Si us plau espera un moment... (També pots fer la migració més tard i manualment anant a Preferències → Altres configuracions → Migrar configuració antiga)"
readonly: "Només lectura"
_chat: _chat:
noMessagesYet: "Encara no tens missatges " noMessagesYet: "Encara no tens missatges "
newMessage: "Missatge nou" newMessage: "Missatge nou"
@ -1372,7 +1371,6 @@ _chat:
muteThisRoom: "Silenciar aquesta sala" muteThisRoom: "Silenciar aquesta sala"
deleteRoom: "Esborrar la sala" deleteRoom: "Esborrar la sala"
chatNotAvailableForThisAccountOrServer: "El xat no està disponible per aquest servidor o aquest compte." chatNotAvailableForThisAccountOrServer: "El xat no està disponible per aquest servidor o aquest compte."
chatIsReadOnlyForThisAccountOrServer: "El xat és només de lectura en aquest servidor o compte. No es poden escriure nous missatges ni crear o unir-se a sales de xat."
chatNotAvailableInOtherAccount: "La funció de xat es troba desactivada al compte de l'altre usuari." chatNotAvailableInOtherAccount: "La funció de xat es troba desactivada al compte de l'altre usuari."
cannotChatWithTheUser: "No pots xatejar amb aquest usuari" cannotChatWithTheUser: "No pots xatejar amb aquest usuari"
cannotChatWithTheUser_description: "El xat està desactivat o l'altra part encara no l'ha obert." cannotChatWithTheUser_description: "El xat està desactivat o l'altra part encara no l'ha obert."
@ -1933,7 +1931,7 @@ _role:
canImportFollowing: "Autoritza la importació de seguidors" canImportFollowing: "Autoritza la importació de seguidors"
canImportMuting: "Autoritza la importació de silenciats" canImportMuting: "Autoritza la importació de silenciats"
canImportUserLists: "Autoritza la importació de llistes d'usuaris " canImportUserLists: "Autoritza la importació de llistes d'usuaris "
chatAvailability: "Es permet xatejar" canChat: "Pot xatejar"
_condition: _condition:
roleAssignedTo: "Assignat a rols manuals" roleAssignedTo: "Assignat a rols manuals"
isLocal: "Usuari local" isLocal: "Usuari local"

View File

@ -1930,6 +1930,7 @@ _role:
canImportFollowing: "Importieren von Gefolgten zulassen" canImportFollowing: "Importieren von Gefolgten zulassen"
canImportMuting: "Importieren von Stummgeschalteten zulassen" canImportMuting: "Importieren von Stummgeschalteten zulassen"
canImportUserLists: "Importieren von Listen erlauben" canImportUserLists: "Importieren von Listen erlauben"
canChat: "Chatten erlauben"
_condition: _condition:
roleAssignedTo: "Manuellen Rollen zugewiesen" roleAssignedTo: "Manuellen Rollen zugewiesen"
isLocal: "Lokaler Benutzer" isLocal: "Lokaler Benutzer"

View File

@ -1930,6 +1930,7 @@ _role:
canImportFollowing: "Allow importing following" canImportFollowing: "Allow importing following"
canImportMuting: "Allow importing muting" canImportMuting: "Allow importing muting"
canImportUserLists: "Allow importing lists" canImportUserLists: "Allow importing lists"
canChat: "Allow Chat"
_condition: _condition:
roleAssignedTo: "Assigned to manual roles" roleAssignedTo: "Assigned to manual roles"
isLocal: "Local user" isLocal: "Local user"

4
locales/index.d.ts vendored
View File

@ -5390,10 +5390,6 @@ export interface Locale extends ILocale {
* *
*/ */
"readonly": string; "readonly": string;
/**
*
*/
"goToDeck": string;
"_chat": { "_chat": {
/** /**
* *

View File

@ -1930,6 +1930,7 @@ _role:
canImportFollowing: "Può importare Following" canImportFollowing: "Può importare Following"
canImportMuting: "Può importare Silenziati" canImportMuting: "Può importare Silenziati"
canImportUserLists: "Può importare liste di Profili" canImportUserLists: "Può importare liste di Profili"
canChat: "Chat consentita"
_condition: _condition:
roleAssignedTo: "Assegnato a ruoli manualmente" roleAssignedTo: "Assegnato a ruoli manualmente"
isLocal: "Profilo locale" isLocal: "Profilo locale"

View File

@ -1343,7 +1343,6 @@ top: "上"
embed: "埋め込み" embed: "埋め込み"
settingsMigrating: "設定を移行しています。しばらくお待ちください... (後ほど、設定→その他→旧設定情報を移行 で手動で移行することもできます)" settingsMigrating: "設定を移行しています。しばらくお待ちください... (後ほど、設定→その他→旧設定情報を移行 で手動で移行することもできます)"
readonly: "読み取り専用" readonly: "読み取り専用"
goToDeck: "デッキへ戻る"
_chat: _chat:
noMessagesYet: "まだメッセージはありません" noMessagesYet: "まだメッセージはありません"

View File

@ -64,8 +64,8 @@ copyNoteId: "노트 ID 복사"
copyFileId: "파일 ID 복사" copyFileId: "파일 ID 복사"
copyFolderId: "폴더 ID 복사" copyFolderId: "폴더 ID 복사"
copyProfileUrl: "프로필 URL 복사" copyProfileUrl: "프로필 URL 복사"
searchUser: "유저 검색" searchUser: "사용자 검색"
searchThisUsersNotes: "유저의 노트를 검색" searchThisUsersNotes: "사용자의 노트 검색"
reply: "답글" reply: "답글"
loadMore: "더 보기" loadMore: "더 보기"
showMore: "더 보기" showMore: "더 보기"
@ -267,7 +267,7 @@ publishing: "배포 중"
notResponding: "응답 없음" notResponding: "응답 없음"
instanceFollowing: "서버의 팔로잉" instanceFollowing: "서버의 팔로잉"
instanceFollowers: "서버의 팔로워" instanceFollowers: "서버의 팔로워"
instanceUsers: "서버의 유저" instanceUsers: "서버의 사용자"
changePassword: "비밀번호 변경" changePassword: "비밀번호 변경"
security: "보안" security: "보안"
retypedNotMatch: "입력이 일치하지 않습니다." retypedNotMatch: "입력이 일치하지 않습니다."
@ -385,12 +385,12 @@ disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리
registration: "등록" registration: "등록"
invite: "초대" invite: "초대"
driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량" driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량"
driveCapacityPerRemoteAccount: "리모트 유저별 드라이브 용량" driveCapacityPerRemoteAccount: "원격 사용자별 드라이브 용량"
inMb: "메가바이트 단위" inMb: "메가바이트 단위"
bannerUrl: "배너 이미지 URL" bannerUrl: "배너 이미지 URL"
backgroundImageUrl: "배경 이미지 URL" backgroundImageUrl: "배경 이미지 URL"
basicInfo: "기본 정보" basicInfo: "기본 정보"
pinnedUsers: "고정한 유저" pinnedUsers: "고정한 사용자"
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다." pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
pinnedPages: "고정한 페이지" pinnedPages: "고정한 페이지"
pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다." pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다."
@ -436,11 +436,11 @@ silence: "사일런스"
silenceConfirm: "이 계정을 사일런스로 설정하시겠습니까?" silenceConfirm: "이 계정을 사일런스로 설정하시겠습니까?"
unsilence: "사일런스 해제" unsilence: "사일런스 해제"
unsilenceConfirm: "이 계정의 사일런스를 해제하시겠습니까?" unsilenceConfirm: "이 계정의 사일런스를 해제하시겠습니까?"
popularUsers: "인기 유저" popularUsers: "인기 사용자"
recentlyUpdatedUsers: "최근에 활동한 유저" recentlyUpdatedUsers: "최근에 활동한 사용자"
recentlyRegisteredUsers: "최근에 가입한 유저" recentlyRegisteredUsers: "최근에 가입한 사용자"
recentlyDiscoveredUsers: "최근에 발견한 유저" recentlyDiscoveredUsers: "최근에 발견한 사용자"
exploreUsersCount: "{count}명의 유저가 있습니다" exploreUsersCount: "{count}명의 사용자가 있습니다"
exploreFediverse: "연합우주를 탐색" exploreFediverse: "연합우주를 탐색"
popularTags: "인기 태그" popularTags: "인기 태그"
userList: "리스트" userList: "리스트"
@ -508,7 +508,7 @@ strongPassword: "강한 비밀번호"
passwordMatched: "일치합니다" passwordMatched: "일치합니다"
passwordNotMatched: "일치하지 않습니다" passwordNotMatched: "일치하지 않습니다"
signinWith: "{x}로 로그인" signinWith: "{x}로 로그인"
signinFailed: "로그인할 수 없습니다. 유저 이름과 비밀번호를 확인해 주십시오." signinFailed: "로그인할 수 없습니다. 사용자 이름과 비밀번호를 확인해 주십시오."
or: "혹은" or: "혹은"
language: "언어" language: "언어"
uiLanguage: "UI 표시 언어" uiLanguage: "UI 표시 언어"
@ -607,7 +607,7 @@ uiInspectorDescription: "메모리에 있는 UI 컴포넌트의 인스턴트 목
output: "출력" output: "출력"
script: "스크립트" script: "스크립트"
disablePagesScript: "Pages 에서 AiScript 를 사용하지 않음" disablePagesScript: "Pages 에서 AiScript 를 사용하지 않음"
updateRemoteUser: "리모트 유저 정보 갱신" updateRemoteUser: "원격 사용자 정보 갱신"
unsetUserAvatar: "아바타 제거" unsetUserAvatar: "아바타 제거"
unsetUserAvatarConfirm: "아바타를 제거할까요?" unsetUserAvatarConfirm: "아바타를 제거할까요?"
unsetUserBanner: "배너 제거" unsetUserBanner: "배너 제거"
@ -616,7 +616,7 @@ deleteAllFiles: "모든 파일 삭제"
deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?" deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?"
removeAllFollowing: "모든 팔로잉 해제" removeAllFollowing: "모든 팔로잉 해제"
removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요." removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요."
userSuspended: "이 유저는 정지되었습니다." userSuspended: "이 사용자는 정지되었습니다."
userSilenced: "이 계정은 사일런스된 상태입니다." userSilenced: "이 계정은 사일런스된 상태입니다."
yourAccountSuspendedTitle: "계정이 정지되었습니다" yourAccountSuspendedTitle: "계정이 정지되었습니다"
yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오." yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오."
@ -677,7 +677,7 @@ emailAddress: "메일 주소"
smtpConfig: "SMTP 서버 설정" smtpConfig: "SMTP 서버 설정"
smtpHost: "호스트" smtpHost: "호스트"
smtpPort: "포트" smtpPort: "포트"
smtpUser: "유저 이름" smtpUser: "사용자 이름"
smtpPass: "비밀번호" smtpPass: "비밀번호"
emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다." emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다."
smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용" smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용"
@ -763,7 +763,7 @@ no: "아니오"
driveFilesCount: "드라이브에 있는 파일 수" driveFilesCount: "드라이브에 있는 파일 수"
driveUsage: "드라이브 사용량" driveUsage: "드라이브 사용량"
noCrawle: "검색엔진의 인덱싱 거부" noCrawle: "검색엔진의 인덱싱 거부"
noCrawleDescription: "검색엔진에 유저 페이지, 노트, 페이지 등의 콘텐츠를 인덱싱되지 않게 합니다." noCrawleDescription: "검색엔진에 사용자 페이지, 노트, 페이지 등의 콘텐츠를 인덱싱되지 않게 합니다."
lockedAccountInfo: "팔로우를 승인으로 승인받더라도 노트의 공개 범위를 '팔로워'로 하지 않는 한 누구나 당신의 노트를 볼 수 있습니다." lockedAccountInfo: "팔로우를 승인으로 승인받더라도 노트의 공개 범위를 '팔로워'로 하지 않는 한 누구나 당신의 노트를 볼 수 있습니다."
alwaysMarkSensitive: "미디어를 항상 열람 주의로 설정" alwaysMarkSensitive: "미디어를 항상 열람 주의로 설정"
loadRawImages: "첨부한 이미지의 썸네일을 원본화질로 표시" loadRawImages: "첨부한 이미지의 썸네일을 원본화질로 표시"
@ -795,7 +795,7 @@ needReloadToApply: "변경 사항은 새로고침하면 적용됩니다."
showTitlebar: "타이틀 바를 표시하기" showTitlebar: "타이틀 바를 표시하기"
clearCache: "캐시 비우기" clearCache: "캐시 비우기"
onlineUsersCount: "{n}명이 접속 중" onlineUsersCount: "{n}명이 접속 중"
nUsers: "{n} 유저" nUsers: "{n} 사용자"
nNotes: "{n} 노트" nNotes: "{n} 노트"
sendErrorReports: "오류 보고서 보내기" sendErrorReports: "오류 보고서 보내기"
sendErrorReportsDescription: "이 설정을 활성화하면, 문제가 발생했을 때 오류에 대한 상세 정보를 Misskey에 보내어 더 나은 소프트웨어를 만드는 데에 도움을 줄 수 있습니다." sendErrorReportsDescription: "이 설정을 활성화하면, 문제가 발생했을 때 오류에 대한 상세 정보를 Misskey에 보내어 더 나은 소프트웨어를 만드는 데에 도움을 줄 수 있습니다."
@ -841,7 +841,7 @@ addDescription: "설명 추가"
userPagePinTip: "각 노트의 메뉴에서 「프로필에 고정」을 선택하는 것으로, 여기에 노트를 표시해 둘 수 있어요." userPagePinTip: "각 노트의 메뉴에서 「프로필에 고정」을 선택하는 것으로, 여기에 노트를 표시해 둘 수 있어요."
notSpecifiedMentionWarning: "수신자가 선택되지 않은 멘션이 있어요" notSpecifiedMentionWarning: "수신자가 선택되지 않은 멘션이 있어요"
info: "정보" info: "정보"
userInfo: "유저 정보" userInfo: "사용자 정보"
unknown: "알 수 없음" unknown: "알 수 없음"
onlineStatus: "온라인 상태" onlineStatus: "온라인 상태"
hideOnlineStatus: "온라인 상태 숨기기" hideOnlineStatus: "온라인 상태 숨기기"
@ -857,7 +857,7 @@ switchAccount: "계정 바꾸기"
enabled: "활성화" enabled: "활성화"
disabled: "비활성화" disabled: "비활성화"
quickAction: "빠른 동작" quickAction: "빠른 동작"
user: "유저" user: "사용자"
administration: "관리" administration: "관리"
accounts: "계정" accounts: "계정"
switch: "전환" switch: "전환"
@ -898,7 +898,7 @@ whatIsNew: "패치 정보 보기"
translate: "번역" translate: "번역"
translatedFrom: "{x}에서 번역" translatedFrom: "{x}에서 번역"
accountDeletionInProgress: "계정 삭제 작업을 진행하고 있습니다" accountDeletionInProgress: "계정 삭제 작업을 진행하고 있습니다"
usernameInfo: "서버상에서 계정을 식별하기 위한 이름. 알파벳(a~z, A~Z), 숫자(0~9) 및 언더바(_)를 사용할 수 있습니다. 유저명은 나중에 변경할 수 없습니다." usernameInfo: "서버상에서 계정을 식별하기 위한 이름. 알파벳(a~z, A~Z), 숫자(0~9) 및 언더바(_)를 사용할 수 있습니다. 사용자명은 나중에 변경할 수 없습니다."
aiChanMode: "아이 모드" aiChanMode: "아이 모드"
devMode: "개발자 모드" devMode: "개발자 모드"
keepCw: "CW 유지하기" keepCw: "CW 유지하기"
@ -1032,7 +1032,7 @@ correspondingSourceIsAvailable: "소스 코드는 {anchor}에서 받아보실
roles: "역할" roles: "역할"
role: "역할" role: "역할"
noRole: "역할이 없습니다" noRole: "역할이 없습니다"
normalUser: "일반 유저" normalUser: "일반 사용자"
undefined: "정의되지 않음" undefined: "정의되지 않음"
assign: "할당" assign: "할당"
unassign: "할당 취소" unassign: "할당 취소"
@ -1106,7 +1106,7 @@ audio: "소리"
audioFiles: "소리" audioFiles: "소리"
dataSaver: "데이터 절약 모드" dataSaver: "데이터 절약 모드"
accountMigration: "계정 이동" accountMigration: "계정 이동"
accountMoved: "이 유저는 다음 계정으로 이사했습니다:" accountMoved: "이 사용자는 다음 계정으로 이사했습니다:"
accountMovedShort: "이사한 계정입니다" accountMovedShort: "이사한 계정입니다"
operationForbidden: "사용할 수 없습니다" operationForbidden: "사용할 수 없습니다"
forceShowAds: "광고를 항상 표시" forceShowAds: "광고를 항상 표시"
@ -1127,8 +1127,8 @@ serverRules: "서버 규칙"
pleaseConfirmBelowBeforeSignup: "이 서버에 가입하기 전에 아래 사항을 확인하여 주십시오." pleaseConfirmBelowBeforeSignup: "이 서버에 가입하기 전에 아래 사항을 확인하여 주십시오."
pleaseAgreeAllToContinue: "계속하시려면 모든 항목에 동의하십시오." pleaseAgreeAllToContinue: "계속하시려면 모든 항목에 동의하십시오."
continue: "계속" continue: "계속"
preservedUsernames: "예약한 유저명" preservedUsernames: "예약한 사용자 이름"
preservedUsernamesDescription: "예약할 유저명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 유저명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다." preservedUsernamesDescription: "예약할 사용자명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 사용자명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다."
createNoteFromTheFile: "이 파일로 노트를 작성" createNoteFromTheFile: "이 파일로 노트를 작성"
archive: "아카이브" archive: "아카이브"
archived: "아카이브 됨" archived: "아카이브 됨"
@ -1142,7 +1142,7 @@ youFollowing: "팔로잉"
preventAiLearning: "기계학습(생성형 AI)으로의 사용을 거부" preventAiLearning: "기계학습(생성형 AI)으로의 사용을 거부"
preventAiLearningDescription: "외부의 문장 생성 AI나 이미지 생성 AI에 대해 제출한 노트나 이미지 등의 콘텐츠를 학습의 대상으로 사용하지 않도록 요구합니다. 다만, 이 요구사항을 지킬 의무는 없기 때문에 학습을 완전히 방지하는 것은 아닙니다." preventAiLearningDescription: "외부의 문장 생성 AI나 이미지 생성 AI에 대해 제출한 노트나 이미지 등의 콘텐츠를 학습의 대상으로 사용하지 않도록 요구합니다. 다만, 이 요구사항을 지킬 의무는 없기 때문에 학습을 완전히 방지하는 것은 아닙니다."
options: "옵션" options: "옵션"
specifyUser: "유저 지정" specifyUser: "사용자 지정"
lookupConfirm: "조회 할까요?" lookupConfirm: "조회 할까요?"
openTagPageConfirm: "해시태그의 페이지를 열까요?" openTagPageConfirm: "해시태그의 페이지를 열까요?"
specifyHost: "호스트 지정" specifyHost: "호스트 지정"
@ -1297,8 +1297,8 @@ passkeyVerificationSucceededButPasswordlessLoginDisabled: "입력된 패스키
messageToFollower: "팔로워에게 보낼 메시지" messageToFollower: "팔로워에게 보낼 메시지"
target: "대상" target: "대상"
testCaptchaWarning: "CAPTCHA를 테스트하기 위한 기능입니다. <strong>실제 환경에서는 사용하지 마세요.</strong>" testCaptchaWarning: "CAPTCHA를 테스트하기 위한 기능입니다. <strong>실제 환경에서는 사용하지 마세요.</strong>"
prohibitedWordsForNameOfUser: "금지 단어 (유저명)" prohibitedWordsForNameOfUser: "금지 단어 (사용자 이름)"
prohibitedWordsForNameOfUserDescription: "이 목록에 포함되는 키워드가 유저명에 있는 경우, 일반 유저는 이름을 바꿀 수 없습니다. 모더레이터 권한을 가진 유저는 제한 대상에서 제외됩니다." prohibitedWordsForNameOfUserDescription: "이 목록에 포함되는 키워드가 사용자 이름에 있는 경우, 일반 사용자는 이름을 바꿀 수 없습니다. 모더레이터 권한을 가진 사용자는 제한 대상에서 제외됩니다."
yourNameContainsProhibitedWords: "바꾸려는 이름에 금지된 키워드가 포함되어 있습니다." yourNameContainsProhibitedWords: "바꾸려는 이름에 금지된 키워드가 포함되어 있습니다."
yourNameContainsProhibitedWordsDescription: "이름에 금지된 키워드가 있습니다. 이름을 사용해야 하는 경우, 서버 관리자에 문의하세요." yourNameContainsProhibitedWordsDescription: "이름에 금지된 키워드가 있습니다. 이름을 사용해야 하는 경우, 서버 관리자에 문의하세요."
thisContentsAreMarkedAsSigninRequiredByAuthor: "게시자에 의해 로그인해야 볼 수 있도록 설정되어 있습니다." thisContentsAreMarkedAsSigninRequiredByAuthor: "게시자에 의해 로그인해야 볼 수 있도록 설정되어 있습니다."
@ -1341,17 +1341,15 @@ right: "오른쪽"
bottom: "아래" bottom: "아래"
top: "위" top: "위"
embed: "임베드" embed: "임베드"
settingsMigrating: "설정을 이전하는 중입니다. 잠시 기다려주십시오... (나중에 '환경설정 → 기타 → 기존 설정 정보를 이전'에서 수동으로 이전할 수도 있습니다)"
readonly: "읽기 전용"
_chat: _chat:
noMessagesYet: "아직 메시지가 없습니다" noMessagesYet: "아직 메시지가 없습니다"
newMessage: "새로운 메시지" newMessage: "새로운 메시지"
individualChat: "개인 대화" individualChat: "개인 대화"
individualChat_description: "특정 유저와 일대일 채팅을 할 수 있습니다." individualChat_description: "특정 사용자와 일대일 채팅을 할 수 있습니다."
roomChat: "룸 채팅" roomChat: "룸 채팅"
roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 유저와도 상대방이 수락하면 채팅을 할 수 있습니다." roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 사용자와도 상대방이 수락하면 채팅을 할 수 있습니다."
createRoom: "룸을 생성" createRoom: "룸을 생성"
inviteUserToChat: "유저를 초대하여 채팅을 시작하세요" inviteUserToChat: "사용자를 초대하여 채팅을 시작하세요"
yourRooms: "생성한 룸" yourRooms: "생성한 룸"
joiningRooms: "참가 중인 룸" joiningRooms: "참가 중인 룸"
invitations: "초대" invitations: "초대"
@ -1359,7 +1357,7 @@ _chat:
history: "이력" history: "이력"
noHistory: "기록이 없습니다" noHistory: "기록이 없습니다"
noRooms: "룸이 없습니다" noRooms: "룸이 없습니다"
inviteUser: "유저를 초대" inviteUser: "사용자를 초대"
sentInvitations: "초대를 보내기" sentInvitations: "초대를 보내기"
join: "참여" join: "참여"
ignore: "무시" ignore: "무시"
@ -1372,22 +1370,21 @@ _chat:
muteThisRoom: "이 룸을 뮤트" muteThisRoom: "이 룸을 뮤트"
deleteRoom: "룸을 삭제" deleteRoom: "룸을 삭제"
chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다." chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다."
chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅방을 만들거나 참가할 수 없습니다."
chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다." chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다."
cannotChatWithTheUser: "이 유저와 채팅을 시작할 수 없습니다" cannotChatWithTheUser: "이 사용자와 채팅을 시작할 수 없습니다"
cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다." cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다."
chatWithThisUser: "채팅하기" chatWithThisUser: "채팅하기"
thisUserAllowsChatOnlyFromFollowers: "이 유저는 팔로워만 채팅을 할 수 있습니다." thisUserAllowsChatOnlyFromFollowers: "이 사용자는 팔로워만 채팅을 할 수 있습니다."
thisUserAllowsChatOnlyFromFollowing: "이 유저는 이 유저가 팔로우하는 유저만 채팅을 허용합니다." thisUserAllowsChatOnlyFromFollowing: "이 사용자는 이 사용자가 팔로우하는 사용자만 채팅을 허용합니다."
thisUserAllowsChatOnlyFromMutualFollowing: "이 유저는 상호 팔로우하는 유저만 채팅을 허용합니다." thisUserAllowsChatOnlyFromMutualFollowing: "이 사용자는 상호 팔로우하는 사용자만 채팅을 허용합니다."
thisUserNotAllowedChatAnyone: "이 유저는 다른 사람의 채팅을 받지 않습니다." thisUserNotAllowedChatAnyone: "이 사용자는 다른 사람의 채팅을 받지 않습니다."
chatAllowedUsers: "채팅을 허용한 상대" chatAllowedUsers: "채팅을 허용한 상대"
chatAllowedUsers_note: "내가 채팅 메시지를 보낸 상대와는 이 설정과 상관없이 채팅이 가능합니다." chatAllowedUsers_note: "내가 채팅 메시지를 보낸 상대와는 이 설정과 상관없이 채팅이 가능합니다."
_chatAllowedUsers: _chatAllowedUsers:
everyone: "누구나" everyone: "누구나"
followers: "자신의 팔로워만" followers: "자신의 팔로워만"
following: "자신이 팔로우한 유저만" following: "자신이 팔로우한 사용자만"
mutual: "상호 팔로우한 유저만" mutual: "상호 팔로우한 사용자만"
none: "아무도 허락하지 않기" none: "아무도 허락하지 않기"
_emojiPalette: _emojiPalette:
palettes: "팔레트" palettes: "팔레트"
@ -1413,7 +1410,7 @@ _settings:
soundsBanner: "클라이언트에서 재생할 소리에 대한 설정을 합니다." soundsBanner: "클라이언트에서 재생할 소리에 대한 설정을 합니다."
timelineAndNote: "타임라인과 노트" timelineAndNote: "타임라인과 노트"
makeEveryTextElementsSelectable: "모든 텍스트 요소를 선택할 수 있도록 함" makeEveryTextElementsSelectable: "모든 텍스트 요소를 선택할 수 있도록 함"
makeEveryTextElementsSelectable_description: "활성화 시, 일부 동작에서 유저의 접근성이 나빠질 수도 있습니다." makeEveryTextElementsSelectable_description: "활성화 시, 일부 동작에서 사용자의 접근성이 나빠질 수도 있습니다."
useStickyIcons: "아이콘이 스크롤을 따라가도록 하기" useStickyIcons: "아이콘이 스크롤을 따라가도록 하기"
showNavbarSubButtons: "내비게이션 바에 보조 버튼 표시" showNavbarSubButtons: "내비게이션 바에 보조 버튼 표시"
ifOn: "켜져 있을 때" ifOn: "켜져 있을 때"
@ -1439,12 +1436,12 @@ _accountSettings:
requireSigninToViewContents: "콘텐츠 열람을 위해 로그인을 필수로 설정하기" requireSigninToViewContents: "콘텐츠 열람을 위해 로그인을 필수로 설정하기"
requireSigninToViewContentsDescription1: "자신이 작성한 모든 노트 등의 콘텐츠를 보기 위해 로그인을 필수로 설정합니다. 크롤러가 정보 수집하는 것을 방지하는 효과를 기대할 수 있습니다." requireSigninToViewContentsDescription1: "자신이 작성한 모든 노트 등의 콘텐츠를 보기 위해 로그인을 필수로 설정합니다. 크롤러가 정보 수집하는 것을 방지하는 효과를 기대할 수 있습니다."
requireSigninToViewContentsDescription2: "URL 미리보기(OGP), 웹페이지에 삽입, 노트 인용을 지원하지 않는 서버에서 볼 수 없게 됩니다." requireSigninToViewContentsDescription2: "URL 미리보기(OGP), 웹페이지에 삽입, 노트 인용을 지원하지 않는 서버에서 볼 수 없게 됩니다."
requireSigninToViewContentsDescription3: "리모트 서버에 연합된 콘텐츠에는 이러한 제한이 적용되지 않을 수 있습니다." requireSigninToViewContentsDescription3: "원격 서버에 연합된 콘텐츠에는 이러한 제한이 적용되지 않을 수 있습니다."
makeNotesFollowersOnlyBefore: "과거 노트는 팔로워만 볼 수 있도록 설정하기" makeNotesFollowersOnlyBefore: "과거 노트는 팔로워만 볼 수 있도록 설정하기"
makeNotesFollowersOnlyBeforeDescription: "이 기능이 활성화되어 있는 동안, 설정된 날짜 및 시간보다 과거 또는 설정된 시간이 지난 노트는 팔로워만 볼 수 있게 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다." makeNotesFollowersOnlyBeforeDescription: "이 기능이 활성화되어 있는 동안, 설정된 날짜 및 시간보다 과거 또는 설정된 시간이 지난 노트는 팔로워만 볼 수 있게 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다."
makeNotesHiddenBefore: "과거 노트 비공개로 전환하기" makeNotesHiddenBefore: "과거 노트 비공개로 전환하기"
makeNotesHiddenBeforeDescription: "이 기능이 활성화되어 있는 동안 설정한 날짜 및 시간보다 과거 또는 설정한 시간이 지난 노트는 본인만 볼 수 있게(비공개로 전환) 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다." makeNotesHiddenBeforeDescription: "이 기능이 활성화되어 있는 동안 설정한 날짜 및 시간보다 과거 또는 설정한 시간이 지난 노트는 본인만 볼 수 있게(비공개로 전환) 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다."
mayNotEffectForFederatedNotes: "리모트 서버에 연합된 노트에는 효과가 없을 수도 있습니다." mayNotEffectForFederatedNotes: "원격 서버에 연합된 노트에는 효과가 없을 수도 있습니다."
mayNotEffectSomeSituations: "여기서 설정하는 제한은 모더레이션이나 리모트 서버에서 볼 때 등 일부 환경에서는 적용되지 않을 수도 있습니다." mayNotEffectSomeSituations: "여기서 설정하는 제한은 모더레이션이나 리모트 서버에서 볼 때 등 일부 환경에서는 적용되지 않을 수도 있습니다."
notesHavePassedSpecifiedPeriod: "지정한 시간이 경과된 노트" notesHavePassedSpecifiedPeriod: "지정한 시간이 경과된 노트"
notesOlderThanSpecifiedDateAndTime: "지정된 날짜 및 시간 이전의 노트" notesOlderThanSpecifiedDateAndTime: "지정된 날짜 및 시간 이전의 노트"
@ -1485,11 +1482,11 @@ _announcement:
needConfirmationToRead: "읽음으로 표시하기 전에 확인하기" needConfirmationToRead: "읽음으로 표시하기 전에 확인하기"
needConfirmationToReadDescription: "활성화하면 이 공지사항을 읽음으로 표시하기 전에 확인 알림창을 띄웁니다. '모두 읽음'의 대상에서도 제외됩니다." needConfirmationToReadDescription: "활성화하면 이 공지사항을 읽음으로 표시하기 전에 확인 알림창을 띄웁니다. '모두 읽음'의 대상에서도 제외됩니다."
end: "공지에서 내리기" end: "공지에서 내리기"
tooManyActiveAnnouncementDescription: "공지사항이 너무 많을 경우, 유저 경험에 영향을 끼칠 가능성이 있습니다. 오래된 공지사항은 아카이브하시는 것을 권장드립니다." tooManyActiveAnnouncementDescription: "공지사항이 너무 많을 경우, 사용자 경험에 영향을 끼칠 가능성이 있습니다. 오래된 공지사항은 아카이브하시는 것을 권장드립니다."
readConfirmTitle: "읽음으로 표시합니까?" readConfirmTitle: "읽음으로 표시합니까?"
readConfirmText: "〈{title}〉의 내용을 읽음으로 표시합니다." readConfirmText: "〈{title}〉의 내용을 읽음으로 표시합니다."
shouldNotBeUsedToPresentPermanentInfo: "신규 유저의 이용 경험에 악영향을 끼칠 수 있으므로, 일시적인 알림 수단으로만 사용하고 고정된 정보에는 사용을 지양하는 것을 추천합니다." shouldNotBeUsedToPresentPermanentInfo: "신규 유저의 이용 경험에 악영향을 끼칠 수 있으므로, 일시적인 알림 수단으로만 사용하고 고정된 정보에는 사용을 지양하는 것을 추천합니다."
dialogAnnouncementUxWarn: "다이얼로그 형태의 알림이 동시에 2개 이상 존재하는 경우, 유저 경험에 악영향을 끼칠 수 있으므로 신중히 결정하십시오." dialogAnnouncementUxWarn: "다이얼로그 형태의 알림이 동시에 2개 이상 존재하는 경우, 사용자 경험에 악영향을 끼칠 수 있으므로 신중히 결정하십시오."
silence: "조용히 알림" silence: "조용히 알림"
silenceDescription: "활성화하면 공지사항에 대한 알림이 가지 않게 되며, 확인 버튼을 누를 필요가 없게 됩니다." silenceDescription: "활성화하면 공지사항에 대한 알림이 가지 않게 되며, 확인 버튼을 누를 필요가 없게 됩니다."
_initialAccountSetting: _initialAccountSetting:
@ -1731,40 +1728,40 @@ _achievements:
flavor: "냐냐냐냐냐냐아아아아앙!" flavor: "냐냐냐냐냐냐아아아아앙!"
_following1: _following1:
title: "첫 팔로우" title: "첫 팔로우"
description: "유저를 처음으로 팔로우했습니다" description: "사용자를 처음으로 팔로우했습니다"
_following10: _following10:
title: "팔로우, 팔로우" title: "팔로우, 팔로우"
description: "10명의 유저를 팔로우했습니다" description: "10명의 사용자를 팔로우했습니다"
_following50: _following50:
title: "친구 잔뜩" title: "친구 잔뜩"
description: "50명의 유저를 팔로우했습니다" description: "50명의 사용자를 팔로우했습니다"
_following100: _following100:
title: "주소록 한 권으론 부족해" title: "주소록 한 권으론 부족해"
description: "100명의 유저를 팔로우했습니다" description: "100명의 사용자를 팔로우했습니다"
_following300: _following300:
title: "친구가 넘쳐나" title: "친구가 넘쳐나"
description: "300명의 유저를 팔로우했습니다" description: "300명의 사용자를 팔로우했습니다"
_followers1: _followers1:
title: "첫 팔로워" title: "첫 팔로워"
description: "유저가 처음으로 팔로잉했습니다" description: "사용자가 처음으로 팔로잉했습니다"
_followers10: _followers10:
title: "팔로우 미!" title: "팔로우 미!"
description: "10명의 유저가 팔로우했습니다" description: "10명의 사용자가 팔로우했습니다"
_followers50: _followers50:
title: "이곳저곳" title: "이곳저곳"
description: "50명의 유저가 팔로우했습니다" description: "50명의 사용자가 팔로우했습니다"
_followers100: _followers100:
title: "인기왕" title: "인기왕"
description: "100명의 유저가 팔로우했습니다" description: "100명의 사용자가 팔로우했습니다"
_followers300: _followers300:
title: "줄 좀 서봐요" title: "줄 좀 서봐요"
description: "100명의 유저가 팔로우했습니다" description: "100명의 사용자가 팔로우했습니다"
_followers500: _followers500:
title: "기지국" title: "기지국"
description: "500명의 유저가 팔로우했습니다" description: "500명의 사용자가 팔로우했습니다"
_followers1000: _followers1000:
title: "유명인사" title: "유명인사"
description: "1,000명의 유저가 팔로우했습니다" description: "1,000명의 사용자가 팔로우했습니다"
_collectAchievements30: _collectAchievements30:
title: "도전 과제 콜렉터" title: "도전 과제 콜렉터"
description: "30개의 도전과제를 획득했습니다" description: "30개의 도전과제를 획득했습니다"
@ -1870,7 +1867,7 @@ _role:
permission: "역할 권한" permission: "역할 권한"
descriptionOfPermission: "<b>조정자</b>는 기본적인 조정 작업을 진행할 수 있습니다.\n<b>관리자</b>는 서버의 모든 설정을 변경할 수 있습니다." descriptionOfPermission: "<b>조정자</b>는 기본적인 조정 작업을 진행할 수 있습니다.\n<b>관리자</b>는 서버의 모든 설정을 변경할 수 있습니다."
assignTarget: "할당 대상" assignTarget: "할당 대상"
descriptionOfAssignTarget: "<b>수동</b>을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n<b>조건부</b>를 선택하면 조건을 설정해 일치하는 유저를 자동으로 포함되게 할 수 있습니다." descriptionOfAssignTarget: "<b>수동</b>을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n<b>조건부</b>를 선택하면 조건을 설정해 일치하는 사용자를 자동으로 포함되게 할 수 있습니다."
manual: "수동" manual: "수동"
manualRoles: "수동 역할" manualRoles: "수동 역할"
conditional: "조건부" conditional: "조건부"
@ -1878,7 +1875,7 @@ _role:
condition: "조건" condition: "조건"
isConditionalRole: "조건부 역할입니다." isConditionalRole: "조건부 역할입니다."
isPublic: "역할 공개" isPublic: "역할 공개"
descriptionOfIsPublic: "역할에 할당된 유저를 누구나 볼 수 있습니다. 또한 유저 프로필에 이 역할이 표시됩니다." descriptionOfIsPublic: "역할에 할당된 사용자를 누구나 볼 수 있습니다. 또한 사용자 프로필에 이 역할이 표시됩니다."
options: "옵션" options: "옵션"
policies: "정책" policies: "정책"
baseRole: "기본 역할" baseRole: "기본 역할"
@ -1891,10 +1888,10 @@ _role:
descriptionOfIsExplorable: "활성화하면 역할 타임라인을 공개합니다. 비활성화 시 타임라인이 공개되지 않습니다." descriptionOfIsExplorable: "활성화하면 역할 타임라인을 공개합니다. 비활성화 시 타임라인이 공개되지 않습니다."
displayOrder: "표시 순서" displayOrder: "표시 순서"
descriptionOfDisplayOrder: "값이 클 수록 UI에서 먼저 표시됩니다." descriptionOfDisplayOrder: "값이 클 수록 UI에서 먼저 표시됩니다."
preserveAssignmentOnMoveAccount: "이전 대상 계정에도 할당 상태 전달" preserveAssignmentOnMoveAccount: "마이그레이션 대상 계정에도 할당 상태 전달"
preserveAssignmentOnMoveAccount_description: "켜면 이 역할이 부여된 계정이 이전될 때 마이그레이션 대상 계정에도 이 역할이 승계됩니다." preserveAssignmentOnMoveAccount_description: "켜면 이 역할이 부여된 계정이 마이그레이션될 때 마이그레이션 대상 계정에도 이 역할이 승계됩니다."
canEditMembersByModerator: "모더레이터의 역할 수정 허용" canEditMembersByModerator: "모더레이터의 역할 수정 허용"
descriptionOfCanEditMembersByModerator: "이 옵션을 켜면 모더레이터도 이 역할에 유저를 할당하거나 삭제할 수 있습니다. 꺼져 있으면 관리자만 할당이 가능합니다." descriptionOfCanEditMembersByModerator: "이 옵션을 켜면 모더레이터도 이 역할에 사용자를 할당하거나 삭제할 수 있습니다. 꺼져 있으면 관리자만 할당이 가능합니다."
priority: "우선순위" priority: "우선순위"
_priority: _priority:
low: "낮음" low: "낮음"
@ -1920,8 +1917,8 @@ _role:
webhookMax: "만들 수 있는 Webhook 수" webhookMax: "만들 수 있는 Webhook 수"
clipMax: "만들 수 있는 클립 수" clipMax: "만들 수 있는 클립 수"
noteEachClipsMax: "클립에 넣을 수 있는 노트 수" noteEachClipsMax: "클립에 넣을 수 있는 노트 수"
userListMax: "만들 수 있는 유저 리스트 수" userListMax: "만들 수 있는 사용자 리스트 수"
userEachUserListsMax: "유저 리스트에 넣을 수 있는 유저 수" userEachUserListsMax: "사용자 리스트에 넣을 수 있는 사용자 수"
rateLimitFactor: "요청 빈도 제한" rateLimitFactor: "요청 빈도 제한"
descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다." descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다."
canHideAds: "광고 숨기기" canHideAds: "광고 숨기기"
@ -1933,24 +1930,24 @@ _role:
canImportFollowing: "팔로우 가져오기 허용" canImportFollowing: "팔로우 가져오기 허용"
canImportMuting: "뮤트 목록 가져오기 허용" canImportMuting: "뮤트 목록 가져오기 허용"
canImportUserLists: "리스트 목록 가져오기 허용" canImportUserLists: "리스트 목록 가져오기 허용"
chatAvailability: "채팅을 허락" canChat: "채팅을 허락"
_condition: _condition:
roleAssignedTo: "수동 역할에 이미 할당됨" roleAssignedTo: "수동 역할에 이미 할당됨"
isLocal: "로컬 유저" isLocal: "로컬 사용자"
isRemote: "리모트 유저" isRemote: "원격 사용자"
isCat: "고양이 유저" isCat: "고양이 사용자"
isBot: "봇 유저" isBot: "봇 사용자"
isSuspended: "정지된 유저" isSuspended: "정지된 사용자"
isLocked: "잠금 계정 유저" isLocked: "잠금 계정 사용자"
isExplorable: "‘계정을 쉽게 발견하도록 하기’를 활성화한 유저" isExplorable: "‘계정을 쉽게 발견하도록 하기’를 활성화한 사용자"
createdLessThan: "가입한 지 다음 일수 이내인 유저" createdLessThan: "가입한 지 다음 일수 이내인 유저"
createdMoreThan: "가입한 지 다음 일수 이상인 유저" createdMoreThan: "가입한 지 다음 일수 이상인 유저"
followersLessThanOrEq: "팔로워 수가 다음 이하인 유저" followersLessThanOrEq: "팔로워 수가 다음 이하인 유저"
followersMoreThanOrEq: "팔로워 수가 다음보다 많은 유저" followersMoreThanOrEq: "팔로워 수가 다음보다 많은 사용자"
followingLessThanOrEq: "팔로잉 수가 다음 이하인 유저" followingLessThanOrEq: "팔로잉 수가 다음 이하인 유저"
followingMoreThanOrEq: "팔로잉 수가 다음보다 많은 유저" followingMoreThanOrEq: "팔로잉 수가 다음보다 많은 사용자"
notesLessThanOrEq: "노트 수가 다음 이하인 유저" notesLessThanOrEq: "노트 수가 다음 이하인 유저"
notesMoreThanOrEq: "노트 수가 다음보다 많은 유저" notesMoreThanOrEq: "노트 수가 다음보다 많은 사용자"
and: "다음을 모두 만족" and: "다음을 모두 만족"
or: "다음을 하나라도 만족" or: "다음을 하나라도 만족"
not: "다음을 만족하지 않음" not: "다음을 만족하지 않음"
@ -1992,7 +1989,7 @@ _ad:
adsSettings: "광고 표시 설정" adsSettings: "광고 표시 설정"
notesPerOneAd: "실시간으로 갱신되는 타임라인에서 광고를 노출시키는 간격 (노트 당)" notesPerOneAd: "실시간으로 갱신되는 타임라인에서 광고를 노출시키는 간격 (노트 당)"
setZeroToDisable: "0으로 지정하면 실시간 타임라인에서의 광고를 비활성화합니다" setZeroToDisable: "0으로 지정하면 실시간 타임라인에서의 광고를 비활성화합니다"
adsTooClose: "광고의 표시 간격이 매우 작아, 유저 경험에 부정적인 영향을 미칠 수 있습니다." adsTooClose: "광고의 표시 간격이 매우 작아, 사용자 경험에 부정적인 영향을 미칠 수 있습니다."
_forgotPassword: _forgotPassword:
enterEmail: "여기에 계정에 등록한 메일 주소를 입력해 주세요. 입력한 메일 주소로 비밀번호 재설정 링크를 발송합니다." enterEmail: "여기에 계정에 등록한 메일 주소를 입력해 주세요. 입력한 메일 주소로 비밀번호 재설정 링크를 발송합니다."
ifNoEmail: "메일 주소를 등록하지 않은 경우, 관리자에 문의해 주십시오." ifNoEmail: "메일 주소를 등록하지 않은 경우, 관리자에 문의해 주십시오."
@ -2247,7 +2244,7 @@ _permissions:
"write:pages": "페이지를 수정합니다" "write:pages": "페이지를 수정합니다"
"read:page-likes": "페이지의 좋아요를 확인합니다" "read:page-likes": "페이지의 좋아요를 확인합니다"
"write:page-likes": "페이지에 좋아요를 추가하거나 취소합니다" "write:page-likes": "페이지에 좋아요를 추가하거나 취소합니다"
"read:user-groups": "유저 그룹 보기" "read:user-groups": "사용자 그룹 보기"
"write:user-groups": "유저 그룹을 만들거나, 초대하거나, 이름을 변경하거나, 양도하거나, 삭제합니다" "write:user-groups": "유저 그룹을 만들거나, 초대하거나, 이름을 변경하거나, 양도하거나, 삭제합니다"
"read:channels": "채널을 보기" "read:channels": "채널을 보기"
"write:channels": "채널을 추가하거나 삭제합니다" "write:channels": "채널을 추가하거나 삭제합니다"
@ -2259,23 +2256,23 @@ _permissions:
"write:flash": "Play를 조작합니다" "write:flash": "Play를 조작합니다"
"read:flash-likes": "Play의 좋아요를 봅니다" "read:flash-likes": "Play의 좋아요를 봅니다"
"write:flash-likes": "Play의 좋아요를 조작합니다" "write:flash-likes": "Play의 좋아요를 조작합니다"
"read:admin:abuse-user-reports": "유저 신고 보기" "read:admin:abuse-user-reports": "사용자 신고 보기"
"write:admin:delete-account": "유저 계정 삭제하기" "write:admin:delete-account": "사용자 계정 삭제하기"
"write:admin:delete-all-files-of-a-user": "모든 유저 파일 삭제하기" "write:admin:delete-all-files-of-a-user": "모든 사용자 파일 삭제하기"
"read:admin:index-stats": "데이터베이스 색인 정보 보기" "read:admin:index-stats": "데이터베이스 색인 정보 보기"
"read:admin:table-stats": "데이터베이스 테이블 정보 보기" "read:admin:table-stats": "데이터베이스 테이블 정보 보기"
"read:admin:user-ips": "유저 IP 주소 보기" "read:admin:user-ips": "사용자 IP 주소 보기"
"read:admin:meta": "인스턴스 메타데이터 보기" "read:admin:meta": "인스턴스 메타데이터 보기"
"write:admin:reset-password": "유저 비밀번호 재설정하기" "write:admin:reset-password": "사용자 비밀번호 재설정하기"
"write:admin:resolve-abuse-user-report": "유저 신고 처리하기" "write:admin:resolve-abuse-user-report": "사용자 신고 처리하기"
"write:admin:send-email": "이메일 보내기" "write:admin:send-email": "이메일 보내기"
"read:admin:server-info": "서버 정보 보기" "read:admin:server-info": "서버 정보 보기"
"read:admin:show-moderation-log": "조정 기록 보기" "read:admin:show-moderation-log": "조정 기록 보기"
"read:admin:show-user": "유저 개인정보 보기" "read:admin:show-user": "사용자 개인정보 보기"
"write:admin:suspend-user": "유저 정지하기" "write:admin:suspend-user": "사용자 정지하기"
"write:admin:unset-user-avatar": "유저 아바타 삭제하기" "write:admin:unset-user-avatar": "사용자 아바타 삭제하기"
"write:admin:unset-user-banner": "유저 배너 삭제하기" "write:admin:unset-user-banner": "사용자 배너 삭제하기"
"write:admin:unsuspend-user": "유저 정지 해제하기" "write:admin:unsuspend-user": "사용자 정지 해제하기"
"write:admin:meta": "인스턴스 메타데이터 수정하기" "write:admin:meta": "인스턴스 메타데이터 수정하기"
"write:admin:user-note": "조정 기록 수정하기" "write:admin:user-note": "조정 기록 수정하기"
"write:admin:roles": "역할 수정하기" "write:admin:roles": "역할 수정하기"
@ -2289,15 +2286,15 @@ _permissions:
"write:admin:avatar-decorations": "아바타 꾸미기 수정하기" "write:admin:avatar-decorations": "아바타 꾸미기 수정하기"
"read:admin:avatar-decorations": "아바타 꾸미기 보기" "read:admin:avatar-decorations": "아바타 꾸미기 보기"
"write:admin:federation": "연합 정보 수정하기" "write:admin:federation": "연합 정보 수정하기"
"write:admin:account": "유저 계정 수정하기" "write:admin:account": "사용자 계정 수정하기"
"read:admin:account": "유저 정보 보기" "read:admin:account": "사용자 정보 보기"
"write:admin:emoji": "이모지 수정하기" "write:admin:emoji": "이모지 수정하기"
"read:admin:emoji": "이모지 보기" "read:admin:emoji": "이모지 보기"
"write:admin:queue": "작업 대기열 수정하기" "write:admin:queue": "작업 대기열 수정하기"
"read:admin:queue": "작업 대기열 정보 보기" "read:admin:queue": "작업 대기열 정보 보기"
"write:admin:promo": "홍보 기록 수정하기" "write:admin:promo": "홍보 기록 수정하기"
"write:admin:drive": "유저 드라이브 수정하기" "write:admin:drive": "사용자 드라이브 수정하기"
"read:admin:drive": "유저 드라이브 정보 보기" "read:admin:drive": "사용자 드라이브 정보 보기"
"read:admin:stream": "관리자용 Websocket API 사용하기" "read:admin:stream": "관리자용 Websocket API 사용하기"
"write:admin:ad": "광고 수정하기" "write:admin:ad": "광고 수정하기"
"read:admin:ad": "광고 보기" "read:admin:ad": "광고 보기"
@ -2319,7 +2316,7 @@ _auth:
callback: "앱으로 돌아갑니다" callback: "앱으로 돌아갑니다"
accepted: "접근 권한이 부여되었습니다." accepted: "접근 권한이 부여되었습니다."
denied: "접근이 거부되었습니다" denied: "접근이 거부되었습니다"
scopeUser: "다음 유저로 활동하고 있습니다." scopeUser: "다음 사용자로 활동하고 있습니다."
pleaseLogin: "어플리케이션의 접근을 허가하려면 로그인하십시오." pleaseLogin: "어플리케이션의 접근을 허가하려면 로그인하십시오."
byClickingYouWillBeRedirectedToThisUrl: "접근을 허용하면 자동으로 다음 URL로 이동합니다." byClickingYouWillBeRedirectedToThisUrl: "접근을 허용하면 자동으로 다음 URL로 이동합니다."
_antennaSources: _antennaSources:
@ -2356,7 +2353,7 @@ _widgets:
postForm: "글 입력란" postForm: "글 입력란"
slideshow: "슬라이드 쇼" slideshow: "슬라이드 쇼"
button: "버튼" button: "버튼"
onlineUsers: "온라인 유저" onlineUsers: "온라인 사용자"
jobQueue: "작업 대기열" jobQueue: "작업 대기열"
serverMetric: "서버 통계" serverMetric: "서버 통계"
aiscript: "AiScript 콘솔" aiscript: "AiScript 콘솔"
@ -2366,7 +2363,7 @@ _widgets:
_userList: _userList:
chooseList: "리스트 선택" chooseList: "리스트 선택"
clicker: "클리커" clicker: "클리커"
birthdayFollowings: "오늘이 생일인 유저" birthdayFollowings: "오늘이 생일인 사용자"
_cw: _cw:
hide: "숨기기" hide: "숨기기"
show: "더 보기" show: "더 보기"
@ -2418,7 +2415,7 @@ _postForm:
f: "작성해주시길 기다리고 있어요..." f: "작성해주시길 기다리고 있어요..."
_profile: _profile:
name: "이름" name: "이름"
username: "유저명" username: "사용자 이름"
description: "자기소개" description: "자기소개"
youCanIncludeHashtags: "해시 태그를 포함할 수 있습니다." youCanIncludeHashtags: "해시 태그를 포함할 수 있습니다."
metadata: "추가 정보" metadata: "추가 정보"
@ -2449,7 +2446,7 @@ _charts:
apRequest: "요청" apRequest: "요청"
usersIncDec: "유저 수 증감" usersIncDec: "유저 수 증감"
usersTotal: "유저 수 합계" usersTotal: "유저 수 합계"
activeUsers: "활동 유저 수" activeUsers: "활동 사용자 수"
notesIncDec: "노트 수 증감" notesIncDec: "노트 수 증감"
localNotesIncDec: "로컬 노트 수 증감" localNotesIncDec: "로컬 노트 수 증감"
remoteNotesIncDec: "리모트 노트 수 증감" remoteNotesIncDec: "리모트 노트 수 증감"
@ -2460,8 +2457,8 @@ _charts:
storageUsageTotal: "스토리지 사용량 합계" storageUsageTotal: "스토리지 사용량 합계"
_instanceCharts: _instanceCharts:
requests: "요청" requests: "요청"
users: "유저 수 차이" users: "사용자 수 차이"
usersTotal: "누적 유저 수" usersTotal: "누적 사용자 수"
notes: "노트 수 증감" notes: "노트 수 증감"
notesTotal: "누적 노트 수" notesTotal: "누적 노트 수"
ff: "팔로잉/팔로워 증감" ff: "팔로잉/팔로워 증감"
@ -2575,18 +2572,18 @@ _notification:
createTokenDescription: "만약 기억이 나지 않는다면 '{text}'를 통해 액세스 토큰을 삭제해 주세요." createTokenDescription: "만약 기억이 나지 않는다면 '{text}'를 통해 액세스 토큰을 삭제해 주세요."
_types: _types:
all: "전부" all: "전부"
note: "유저의 새 글" note: "사용자의 새 글"
follow: "팔로잉" follow: "팔로잉"
mention: "멘션" mention: "멘션"
reply: "답글" reply: "답글"
renote: "리노트" renote: "리노트"
quote: "인용" quote: "인용"
reaction: "리액션" reaction: "반응"
pollEnded: "투표가 종료됨" pollEnded: "투표가 종료됨"
receiveFollowRequest: "팔로우 요청을 받았을 때" receiveFollowRequest: "팔로우 요청을 받았을 때"
followRequestAccepted: "팔로우 요청이 승인되었을 때" followRequestAccepted: "팔로우 요청이 승인되었을 때"
roleAssigned: "역할이 부여됨" roleAssigned: "역할이 부여 됨"
chatRoomInvitationReceived: "채팅 룸에 초대받" chatRoomInvitationReceived: "채팅 룸에 초대받았습니다"
achievementEarned: "도전 과제 획득" achievementEarned: "도전 과제 획득"
exportCompleted: "추출을 성공함" exportCompleted: "추출을 성공함"
login: "로그인" login: "로그인"
@ -2674,10 +2671,10 @@ _abuseReport:
mail: "이메일" mail: "이메일"
webhook: "Webhook" webhook: "Webhook"
_captions: _captions:
mail: "모더레이터 권한을 가진 유저의 이메일 주소에 알림을 보냅니다 (신고를 받은 때에만)" mail: "모더레이터 권한을 가진 사용자의 이메일 주소에 알림을 보냅니다 (신고를 받은 때에만)"
webhook: "지정한 SystemWebhook에 알림을 보냅니다 (신고를 받은 때와 해결했을 때에 송신)" webhook: "지정한 SystemWebhook에 알림을 보냅니다 (신고를 받은 때와 해결했을 때에 송신)"
keywords: "키워드" keywords: "키워드"
notifiedUser: "알릴 유저" notifiedUser: "알릴 사용자"
notifiedWebhook: "사용할 Webhook" notifiedWebhook: "사용할 Webhook"
deleteConfirm: "수신자를 삭제하시겠습니까?" deleteConfirm: "수신자를 삭제하시겠습니까?"
_moderationLogTypes: _moderationLogTypes:
@ -2696,11 +2693,11 @@ _moderationLogTypes:
deleteDriveFile: "파일 삭제" deleteDriveFile: "파일 삭제"
deleteNote: "노트 삭제" deleteNote: "노트 삭제"
createGlobalAnnouncement: "전역 공지사항 생성" createGlobalAnnouncement: "전역 공지사항 생성"
createUserAnnouncement: "유저에게 공지사항 만들기" createUserAnnouncement: "사용자 공지사항 만들기"
updateGlobalAnnouncement: "모든 공지사항 수정" updateGlobalAnnouncement: "모든 공지사항 수정"
updateUserAnnouncement: "유저의 공지사항 수정" updateUserAnnouncement: "사용자 공지사항 수정"
deleteGlobalAnnouncement: "모든 공지사항 삭제" deleteGlobalAnnouncement: "모든 공지사항 삭제"
deleteUserAnnouncement: "유저의 공지사항 삭제" deleteUserAnnouncement: "사용자 공지사항 삭제"
resetPassword: "비밀번호 재설정" resetPassword: "비밀번호 재설정"
suspendRemoteInstance: "리모트 서버를 정지" suspendRemoteInstance: "리모트 서버를 정지"
unsuspendRemoteInstance: "리모트 서버의 정지를 해제" unsuspendRemoteInstance: "리모트 서버의 정지를 해제"
@ -2942,7 +2939,7 @@ _embedCodeGen:
_selfXssPrevention: _selfXssPrevention:
warning: "경고" warning: "경고"
title: "“이 화면에 뭔가를 붙여넣어라\"는 것은 모두 사기입니다." title: "“이 화면에 뭔가를 붙여넣어라\"는 것은 모두 사기입니다."
description1: "여기에 무언가를 붙여넣으면 악의적인 유저에게 계정을 탈취당하거나 개인정보를 도용당할 수 있습니다." description1: "여기에 무언가를 붙여넣으면 악의적인 사용자에게 계정을 탈취당하거나 개인정보를 도용당할 수 있습니다."
description2: "붙여 넣으려는 항목이 무엇인지 정확히 이해하지 못하는 경우, %c지금 바로 작업을 중단하고 이 창을 닫으십시오." description2: "붙여 넣으려는 항목이 무엇인지 정확히 이해하지 못하는 경우, %c지금 바로 작업을 중단하고 이 창을 닫으십시오."
description3: "자세한 내용은 여기를 확인해 주세요. {link}" description3: "자세한 내용은 여기를 확인해 주세요. {link}"
_followRequest: _followRequest:
@ -2993,7 +2990,7 @@ _search:
searchScopeAll: "전체" searchScopeAll: "전체"
searchScopeLocal: "로컬" searchScopeLocal: "로컬"
searchScopeServer: "서버 지정" searchScopeServer: "서버 지정"
searchScopeUser: "유저 지정" searchScopeUser: "사용자 지정"
pleaseEnterServerHost: "서버의 호스트를 입력해 주세요." pleaseEnterServerHost: "서버의 호스트를 입력해 주세요."
pleaseSelectUser: "유저를 선택해주세요" pleaseSelectUser: "유저를 선택해주세요"
serverHostPlaceholder: "예: misskey.example.com" serverHostPlaceholder: "예: misskey.example.com"

View File

@ -1341,8 +1341,6 @@ right: "右"
bottom: "下" bottom: "下"
top: "上" top: "上"
embed: "嵌入" embed: "嵌入"
settingsMigrating: "正在迁移设置,请稍候。(之后也可以在设置 → 其它 → 迁移旧设置来手动迁移)"
readonly: "只读"
_chat: _chat:
noMessagesYet: "还没有消息" noMessagesYet: "还没有消息"
newMessage: "新消息" newMessage: "新消息"
@ -1372,7 +1370,6 @@ _chat:
muteThisRoom: "静音此房间" muteThisRoom: "静音此房间"
deleteRoom: "删除房间" deleteRoom: "删除房间"
chatNotAvailableForThisAccountOrServer: "此服务器或者账户还未开启聊天功能。" chatNotAvailableForThisAccountOrServer: "此服务器或者账户还未开启聊天功能。"
chatIsReadOnlyForThisAccountOrServer: "此服务器或者账户内的聊天为只读。无法发布新信息或创建及加入群聊。"
chatNotAvailableInOtherAccount: "对方账户目前处于无法使用聊天的状态。" chatNotAvailableInOtherAccount: "对方账户目前处于无法使用聊天的状态。"
cannotChatWithTheUser: "无法与此用户聊天" cannotChatWithTheUser: "无法与此用户聊天"
cannotChatWithTheUser_description: "可能现在无法使用聊天,或者对方未开启聊天。" cannotChatWithTheUser_description: "可能现在无法使用聊天,或者对方未开启聊天。"
@ -1932,7 +1929,7 @@ _role:
canImportFollowing: "允许导入关注列表" canImportFollowing: "允许导入关注列表"
canImportMuting: "允许导入隐藏列表" canImportMuting: "允许导入隐藏列表"
canImportUserLists: "允许导入用户列表" canImportUserLists: "允许导入用户列表"
chatAvailability: "允许聊天" canChat: "允许聊天"
_condition: _condition:
roleAssignedTo: "已分配给手动角色" roleAssignedTo: "已分配给手动角色"
isLocal: "是本地用户" isLocal: "是本地用户"

View File

@ -1342,7 +1342,6 @@ bottom: "下"
top: "上" top: "上"
embed: "嵌入" embed: "嵌入"
settingsMigrating: "正在移轉設定。請稍候……(之後也可以到「設定 → 其他 → 舊設定資訊移轉」中手動進行移轉)" settingsMigrating: "正在移轉設定。請稍候……(之後也可以到「設定 → 其他 → 舊設定資訊移轉」中手動進行移轉)"
readonly: "唯讀"
_chat: _chat:
noMessagesYet: "尚無訊息" noMessagesYet: "尚無訊息"
newMessage: "新訊息" newMessage: "新訊息"
@ -1372,7 +1371,6 @@ _chat:
muteThisRoom: "此聊天室已靜音" muteThisRoom: "此聊天室已靜音"
deleteRoom: "刪除聊天室" deleteRoom: "刪除聊天室"
chatNotAvailableForThisAccountOrServer: "這個伺服器或這個帳號的聊天功能尚未啟用。" chatNotAvailableForThisAccountOrServer: "這個伺服器或這個帳號的聊天功能尚未啟用。"
chatIsReadOnlyForThisAccountOrServer: "在此伺服器或此帳戶上的聊天是唯讀的。您無法發布新訊息、建立或加入聊天室。"
chatNotAvailableInOtherAccount: "對方的帳號無法使用聊天功能。" chatNotAvailableInOtherAccount: "對方的帳號無法使用聊天功能。"
cannotChatWithTheUser: "無法與此使用者聊天" cannotChatWithTheUser: "無法與此使用者聊天"
cannotChatWithTheUser_description: "聊天功能目前無法使用,或對方尚未開放聊天功能。" cannotChatWithTheUser_description: "聊天功能目前無法使用,或對方尚未開放聊天功能。"
@ -1438,7 +1436,7 @@ _preferencesBackup:
_accountSettings: _accountSettings:
requireSigninToViewContents: "須登入以顯示內容" requireSigninToViewContents: "須登入以顯示內容"
requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。" requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。"
requireSigninToViewContentsDescription2: "針對您貼文的 URL 預覽 (OGP) 與網頁嵌入功能將會無法使用。而不支援引用貼文的伺服器,也將停止顯示。" requireSigninToViewContentsDescription2: "來自不支援 URL 預覽 (OGP)、 網頁嵌入和引用貼文的伺服器,也將停止顯示。"
requireSigninToViewContentsDescription3: "這些限制可能不適用於被聯邦發送至遠端伺服器的內容。" requireSigninToViewContentsDescription3: "這些限制可能不適用於被聯邦發送至遠端伺服器的內容。"
makeNotesFollowersOnlyBefore: "讓過去的貼文僅對追隨者顯示" makeNotesFollowersOnlyBefore: "讓過去的貼文僅對追隨者顯示"
makeNotesFollowersOnlyBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對追隨者顯示。 如果您再次停用它,貼文的公開狀態也會恢復原狀。" makeNotesFollowersOnlyBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對追隨者顯示。 如果您再次停用它,貼文的公開狀態也會恢復原狀。"
@ -1933,7 +1931,7 @@ _role:
canImportFollowing: "允許匯入追隨名單" canImportFollowing: "允許匯入追隨名單"
canImportMuting: "允許匯入靜音名單" canImportMuting: "允許匯入靜音名單"
canImportUserLists: "允許匯入清單" canImportUserLists: "允許匯入清單"
chatAvailability: "允許聊天" canChat: "允許聊天"
_condition: _condition:
roleAssignedTo: "手動指派角色完成" roleAssignedTo: "手動指派角色完成"
isLocal: "本地使用者" isLocal: "本地使用者"

View File

@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2025.4.0-rc.4", "version": "2025.4.0-rc.3",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -117,7 +117,7 @@ windowRouter.addListener('change', ctx => {
windowRouter.init(); windowRouter.init();
provide(DI.router, windowRouter); provide(DI.router, windowRouter);
provide(DI.inAppSearchMarkerId, searchMarkerId); provide('inAppSearchMarkerId', searchMarkerId);
provideMetadataReceiver((metadataGetter) => { provideMetadataReceiver((metadataGetter) => {
const info = metadataGetter(); const info = metadataGetter();
pageMetadata.value = info; pageMetadata.value = info;
@ -125,7 +125,7 @@ provideMetadataReceiver((metadataGetter) => {
provideReactiveMetadata(pageMetadata); provideReactiveMetadata(pageMetadata);
provide('shouldOmitHeaderTitle', true); provide('shouldOmitHeaderTitle', true);
provide('shouldHeaderThin', true); provide('shouldHeaderThin', true);
provide(DI.forceSpacerMin, true); provide('forceSpacerMin', true);
const contextmenu = computed(() => ([{ const contextmenu = computed(() => ([{
icon: 'ti ti-player-eject', icon: 'ti ti-player-eject',

View File

@ -14,7 +14,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup> <script lang="ts" setup>
import { inject } from 'vue'; import { inject } from 'vue';
import { deviceKind } from '@/utility/device-kind.js'; import { deviceKind } from '@/utility/device-kind.js';
import { DI } from '@/di.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
contentMax?: number | null; contentMax?: number | null;
@ -26,7 +25,7 @@ const props = withDefaults(defineProps<{
marginMax: 24, marginMax: 24,
}); });
const forceSpacerMin = inject(DI.forceSpacerMin, false) || deviceKind === 'smartphone'; const forceSpacerMin = inject('forceSpacerMin', false) || deviceKind === 'smartphone';
</script> </script>
<style lang="scss" module> <style lang="scss" module>

View File

@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div ref="root" :class="[$style.root, { [$style.highlighted]: highlighted }]"> <div ref="root" :class="[$style.root, { [$style.highlighted]: highlighted }]">
<slot :isParentOfTarget="isParentOfTarget"></slot> <slot></slot>
</div> </div>
</template> </template>
@ -21,7 +21,7 @@ import {
useTemplateRef, useTemplateRef,
inject, inject,
} from 'vue'; } from 'vue';
import { DI } from '@/di.js'; import type { Ref } from 'vue';
const props = defineProps<{ const props = defineProps<{
markerId?: string; markerId?: string;
@ -36,13 +36,12 @@ const rootEl = useTemplateRef('root');
const rootElMutationObserver = new MutationObserver(() => { const rootElMutationObserver = new MutationObserver(() => {
checkChildren(); checkChildren();
}); });
const injectedSearchMarkerId = inject(DI.inAppSearchMarkerId, null); const injectedSearchMarkerId = inject<Ref<string | null> | null>('inAppSearchMarkerId', null);
const searchMarkerId = computed(() => injectedSearchMarkerId?.value ?? window.location.hash.slice(1)); const searchMarkerId = computed(() => injectedSearchMarkerId?.value ?? window.location.hash.slice(1));
const highlighted = ref(props.markerId === searchMarkerId.value); const highlighted = ref(props.markerId === searchMarkerId.value);
const isParentOfTarget = computed(() => props.children?.includes(searchMarkerId.value));
function checkChildren() { function checkChildren() {
if (isParentOfTarget.value) { if (props.children?.includes(searchMarkerId.value)) {
const el = window.document.querySelector(`[data-in-app-search-marker-id="${searchMarkerId.value}"]`); const el = window.document.querySelector(`[data-in-app-search-marker-id="${searchMarkerId.value}"]`);
highlighted.value = el == null; highlighted.value = el == null;
} }
@ -106,8 +105,8 @@ onBeforeUnmount(dispose);
@keyframes blink { @keyframes blink {
0%, 100% { 0%, 100% {
background: color(from var(--MI_THEME-accent) srgb r g b / 0.1); background: color(from var(--MI_THEME-accent) srgb r g b / 0.05);
border: 1px solid color(from var(--MI_THEME-accent) srgb r g b / 0.75); border: 1px solid color(from var(--MI_THEME-accent) srgb r g b / 0.7);
} }
50% { 50% {
background: transparent; background: transparent;

View File

@ -16,6 +16,4 @@ export const DI = {
currentStickyBottom: Symbol() as InjectionKey<Ref<number>>, currentStickyBottom: Symbol() as InjectionKey<Ref<number>>,
mfmEmojiReactCallback: Symbol() as InjectionKey<(emoji: string) => void>, mfmEmojiReactCallback: Symbol() as InjectionKey<(emoji: string) => void>,
inModal: Symbol() as InjectionKey<boolean>, inModal: Symbol() as InjectionKey<boolean>,
inAppSearchMarkerId: Symbol() as InjectionKey<Ref<string | null>>,
forceSpacerMin: Symbol() as InjectionKey<boolean>,
}; };

View File

@ -341,7 +341,7 @@ defineExpose({
box-sizing: border-box; box-sizing: border-box;
border-right: solid 0.5px var(--MI_THEME-divider); border-right: solid 0.5px var(--MI_THEME-divider);
overflow: auto; overflow: auto;
height: 100cqh; height: 100dvh;
} }
> .main { > .main {

View File

@ -11,8 +11,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFeatureBanner> </MkFeatureBanner>
<div class="_gaps_s"> <div class="_gaps_s">
<SearchMarker v-slot="slotProps" :keywords="['general']"> <SearchMarker :keywords="['general']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.general }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.general }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-settings"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-settings"></i></SearchIcon></template>
@ -108,8 +108,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker v-slot="slotProps" :keywords="['timeline', 'note']"> <SearchMarker :keywords="['timeline', 'note']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts._settings.timelineAndNote }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts._settings.timelineAndNote }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-notes"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-notes"></i></SearchIcon></template>
@ -276,8 +276,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker v-slot="slotProps" :keywords="['post', 'form']"> <SearchMarker :keywords="['post', 'form']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.postForm }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.postForm }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-edit"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-edit"></i></SearchIcon></template>
@ -338,8 +338,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker v-slot="slotProps" :keywords="['notification']"> <SearchMarker :keywords="['notification']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.notifications }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.notifications }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-bell"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-bell"></i></SearchIcon></template>
@ -380,8 +380,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</SearchMarker> </SearchMarker>
<template v-if="$i.policies.chatAvailability !== 'unavailable'"> <template v-if="$i.policies.chatAvailability !== 'unavailable'">
<SearchMarker v-slot="slotProps" :keywords="['chat', 'messaging']"> <SearchMarker :keywords="['chat', 'messaging']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.chat }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.chat }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-messages"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-messages"></i></SearchIcon></template>
@ -420,8 +420,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</SearchMarker> </SearchMarker>
</template> </template>
<SearchMarker v-slot="slotProps" :keywords="['accessibility']"> <SearchMarker :keywords="['accessibility']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.accessibility }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.accessibility }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-accessible"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-accessible"></i></SearchIcon></template>
@ -530,8 +530,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker v-slot="slotProps" :keywords="['performance']"> <SearchMarker :keywords="['performance']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.performance }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.performance }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-battery-vertical-eco"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-battery-vertical-eco"></i></SearchIcon></template>
@ -566,8 +566,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker v-slot="slotProps" :keywords="['datasaver']"> <SearchMarker :keywords="['datasaver']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.dataSaver }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-antenna-bars-3"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-antenna-bars-3"></i></SearchIcon></template>
@ -600,8 +600,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkFolder> </MkFolder>
</SearchMarker> </SearchMarker>
<SearchMarker v-slot="slotProps" :keywords="['other']"> <SearchMarker :keywords="['other']">
<MkFolder :defaultOpen="slotProps.isParentOfTarget"> <MkFolder>
<template #label><SearchLabel>{{ i18n.ts.other }}</SearchLabel></template> <template #label><SearchLabel>{{ i18n.ts.other }}</SearchLabel></template>
<template #icon><SearchIcon><i class="ti ti-settings-cog"></i></SearchIcon></template> <template #icon><SearchIcon><i class="ti ti-settings-cog"></i></SearchIcon></template>

View File

@ -211,12 +211,15 @@ import FormLink from '@/components/form/link.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import MkThemePreview from '@/components/MkThemePreview.vue'; import MkThemePreview from '@/components/MkThemePreview.vue';
import { getBuiltinThemesRef, getThemesRef } from '@/theme.js'; import { getBuiltinThemesRef, getThemesRef } from '@/theme.js';
import { selectFile } from '@/utility/select-file.js';
import { isDeviceDarkmode } from '@/utility/is-device-darkmode.js'; import { isDeviceDarkmode } from '@/utility/is-device-darkmode.js';
import { store } from '@/store.js'; import { store } from '@/store.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js'; import { instance } from '@/instance.js';
import { uniqueBy } from '@/utility/array.js'; import { uniqueBy } from '@/utility/array.js';
import { definePage } from '@/page.js'; import { definePage } from '@/page.js';
import { miLocalStorage } from '@/local-storage.js';
import { reloadAsk } from '@/utility/reload-ask.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
const installedThemes = getThemesRef(); const installedThemes = getThemesRef();

View File

@ -4,59 +4,6 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_menuDrawerBg_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_menuDrawerBg_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_menuDrawerBg_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawerBg_leaveTo : ''"
>
<div
v-if="drawerMenuShowing"
:class="$style.menuDrawerBg"
class="_modalBg"
@click="drawerMenuShowing = false"
@touchstart.passive="drawerMenuShowing = false"
></div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_menuDrawer_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_menuDrawer_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_menuDrawer_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawer_leaveTo : ''"
>
<div v-if="drawerMenuShowing" :class="$style.menuDrawer">
<XDrawerMenu/>
</div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_leaveTo : ''"
>
<div
v-if="widgetsShowing"
:class="$style.widgetsDrawerBg"
class="_modalBg"
@click="widgetsShowing = false"
@touchstart.passive="widgetsShowing = false"
></div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_widgetsDrawer_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_widgetsDrawer_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_widgetsDrawer_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_widgetsDrawer_leaveTo : ''"
>
<div v-if="widgetsShowing" :class="$style.widgetsDrawer">
<button class="_button" :class="$style.widgetsCloseButton" @click="widgetsShowing = false"><i class="ti ti-x"></i></button>
<XWidgets/>
</div>
</Transition>
<component <component
:is="popup.component" :is="popup.component"
v-for="popup in popups" v-for="popup in popups"
@ -112,14 +59,9 @@ import { useStream } from '@/stream.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { globalEvents } from '@/events.js'; import { globalEvents } from '@/events.js';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
const XStreamIndicator = defineAsyncComponent(() => import('./stream-indicator.vue')); const XStreamIndicator = defineAsyncComponent(() => import('./stream-indicator.vue'));
const XUpload = defineAsyncComponent(() => import('./upload.vue')); const XUpload = defineAsyncComponent(() => import('./upload.vue'));
const XWidgets = defineAsyncComponent(() => import('./widgets.vue'));
const drawerMenuShowing = defineModel<boolean>('drawerMenuShowing');
const widgetsShowing = defineModel<boolean>('widgetsShowing');
const dev = _DEV_; const dev = _DEV_;
@ -158,50 +100,6 @@ if ($i) {
</script> </script>
<style lang="scss" module> <style lang="scss" module>
.transition_menuDrawerBg_enterActive,
.transition_menuDrawerBg_leaveActive {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_menuDrawerBg_enterFrom,
.transition_menuDrawerBg_leaveTo {
opacity: 0;
}
.transition_menuDrawer_enterActive,
.transition_menuDrawer_leaveActive {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_menuDrawer_enterFrom,
.transition_menuDrawer_leaveTo {
opacity: 0;
transform: translateX(-240px);
}
.transition_widgetsDrawerBg_enterActive,
.transition_widgetsDrawerBg_leaveActive {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_widgetsDrawerBg_enterFrom,
.transition_widgetsDrawerBg_leaveTo {
opacity: 0;
}
.transition_widgetsDrawer_enterActive,
.transition_widgetsDrawer_leaveActive {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_widgetsDrawer_enterFrom,
.transition_widgetsDrawer_leaveTo {
opacity: 0;
transform: translateX(-240px);
}
.transition_notification_move, .transition_notification_move,
.transition_notification_enterActive, .transition_notification_enterActive,
.transition_notification_leaveActive { .transition_notification_leaveActive {
@ -216,54 +114,6 @@ if ($i) {
transform: translateX(-250px); transform: translateX(-250px);
} }
.menuDrawerBg {
z-index: 1001;
}
.menuDrawer {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
height: 100dvh;
width: 240px;
box-sizing: border-box;
contain: strict;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-navBg);
}
.widgetsDrawerBg {
z-index: 1001;
}
.widgetsDrawer {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: 310px;
height: 100dvh;
padding: var(--MI-margin) var(--MI-margin) calc(var(--MI-margin) + env(safe-area-inset-bottom, 0px)) !important;
box-sizing: border-box;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-bg);
}
.widgetsCloseButton {
padding: 8px;
display: block;
margin: 0 auto;
}
@media (min-width: 370px) {
.widgetsCloseButton {
display: none;
}
}
.notifications { .notifications {
position: fixed; position: fixed;
z-index: 3900000; z-index: 3900000;

View File

@ -71,7 +71,60 @@ SPDX-License-Identifier: AGPL-3.0-only
<XMobileFooterMenu v-if="isMobile" v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/> <XMobileFooterMenu v-if="isMobile" v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/>
</div> </div>
<XCommon v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/> <Transition
:enterActiveClass="prefer.s.animation ? $style.transition_menuDrawerBg_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_menuDrawerBg_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_menuDrawerBg_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawerBg_leaveTo : ''"
>
<div
v-if="drawerMenuShowing"
:class="$style.menuBg"
class="_modalBg"
@click="drawerMenuShowing = false"
@touchstart.passive="drawerMenuShowing = false"
></div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_menuDrawer_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_menuDrawer_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_menuDrawer_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawer_leaveTo : ''"
>
<div v-if="drawerMenuShowing" :class="$style.menu">
<XDrawerMenu/>
</div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_leaveTo : ''"
>
<div
v-if="widgetsShowing"
:class="$style.widgetsDrawerBg"
class="_modalBg"
@click="widgetsShowing = false"
@touchstart.passive="widgetsShowing = false"
></div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_widgetsDrawer_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_widgetsDrawer_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_widgetsDrawer_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_widgetsDrawer_leaveTo : ''"
>
<div v-if="widgetsShowing" :class="$style.widgetsDrawer">
<button class="_button" :class="$style.widgetsCloseButton" @click="widgetsShowing = false"><i class="ti ti-x"></i></button>
<XWidgets/>
</div>
</Transition>
<XCommon/>
</div> </div>
</template> </template>
@ -81,6 +134,7 @@ import { v4 as uuid } from 'uuid';
import XCommon from './_common_/common.vue'; import XCommon from './_common_/common.vue';
import XSidebar from '@/ui/_common_/navbar.vue'; import XSidebar from '@/ui/_common_/navbar.vue';
import XNavbarH from '@/ui/_common_/navbar-h.vue'; import XNavbarH from '@/ui/_common_/navbar-h.vue';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue'; import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { $i } from '@/i.js'; import { $i } from '@/i.js';
@ -102,6 +156,7 @@ import { columns, layout, columnTypes, switchProfileMenu, addColumn as addColumn
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue')); const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue')); const XAnnouncements = defineAsyncComponent(() => import('@/ui/_common_/announcements.vue'));
const XWidgets = defineAsyncComponent(() => import('./_common_/widgets.vue'));
const columnComponents = { const columnComponents = {
main: XMainColumn, main: XMainColumn,
@ -214,6 +269,50 @@ if (prefer.s['deck.wallpaper'] != null) {
</script> </script>
<style lang="scss" module> <style lang="scss" module>
.transition_menuDrawerBg_enterActive,
.transition_menuDrawerBg_leaveActive {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_menuDrawerBg_enterFrom,
.transition_menuDrawerBg_leaveTo {
opacity: 0;
}
.transition_menuDrawer_enterActive,
.transition_menuDrawer_leaveActive {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_menuDrawer_enterFrom,
.transition_menuDrawer_leaveTo {
opacity: 0;
transform: translateX(-240px);
}
.transition_widgetsDrawerBg_enterActive,
.transition_widgetsDrawerBg_leaveActive {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_widgetsDrawerBg_enterFrom,
.transition_widgetsDrawerBg_leaveTo {
opacity: 0;
}
.transition_widgetsDrawer_enterActive,
.transition_widgetsDrawer_leaveActive {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_widgetsDrawer_enterFrom,
.transition_widgetsDrawer_leaveTo {
opacity: 0;
transform: translateX(-240px);
}
.root { .root {
$nav-hide-threshold: 650px; // TODO: $nav-hide-threshold: 650px; // TODO:
@ -245,9 +344,6 @@ if (prefer.s['deck.wallpaper'] != null) {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
//
min-height: 0;
} }
.columns { .columns {
@ -345,4 +441,52 @@ if (prefer.s['deck.wallpaper'] != null) {
.bottomMenuRight { .bottomMenuRight {
margin-left: auto; margin-left: auto;
} }
.menuBg {
z-index: 1001;
}
.menu {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
height: 100dvh;
width: 240px;
box-sizing: border-box;
contain: strict;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-navBg);
}
.widgetsDrawerBg {
z-index: 1001;
}
.widgetsDrawer {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: 310px;
height: 100dvh;
padding: var(--MI-margin) var(--MI-margin) calc(var(--MI-margin) + env(safe-area-inset-bottom, 0px)) !important;
box-sizing: border-box;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-bg);
}
.widgetsCloseButton {
padding: 8px;
display: block;
margin: 0 auto;
}
@media (min-width: 370px) {
.widgetsCloseButton {
display: none;
}
}
</style> </style>

View File

@ -49,11 +49,10 @@ import { updateColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownCo
import * as os from '@/os.js'; import * as os from '@/os.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { prefer } from '@/preferences.js'; import { prefer } from '@/preferences.js';
import { DI } from '@/di.js';
provide('shouldHeaderThin', true); provide('shouldHeaderThin', true);
provide('shouldOmitHeaderTitle', true); provide('shouldOmitHeaderTitle', true);
provide(DI.forceSpacerMin, true); provide('forceSpacerMin', true);
const withWallpaper = prefer.s['deck.wallpaper'] != null; const withWallpaper = prefer.s['deck.wallpaper'] != null;

View File

@ -22,7 +22,60 @@ SPDX-License-Identifier: AGPL-3.0-only
<XWidgets/> <XWidgets/>
</div> </div>
<XCommon v-model:drawerMenuShowing="drawerMenuShowing" v-model:widgetsShowing="widgetsShowing"/> <Transition
:enterActiveClass="prefer.s.animation ? $style.transition_menuDrawerBg_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_menuDrawerBg_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_menuDrawerBg_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawerBg_leaveTo : ''"
>
<div
v-if="drawerMenuShowing"
:class="$style.menuDrawerBg"
class="_modalBg"
@click="drawerMenuShowing = false"
@touchstart.passive="drawerMenuShowing = false"
></div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_menuDrawer_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_menuDrawer_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_menuDrawer_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_menuDrawer_leaveTo : ''"
>
<div v-if="drawerMenuShowing" :class="$style.menuDrawer">
<XDrawerMenu/>
</div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_widgetsDrawerBg_leaveTo : ''"
>
<div
v-if="widgetsShowing"
:class="$style.widgetsDrawerBg"
class="_modalBg"
@click="widgetsShowing = false"
@touchstart.passive="widgetsShowing = false"
></div>
</Transition>
<Transition
:enterActiveClass="prefer.s.animation ? $style.transition_widgetsDrawer_enterActive : ''"
:leaveActiveClass="prefer.s.animation ? $style.transition_widgetsDrawer_leaveActive : ''"
:enterFromClass="prefer.s.animation ? $style.transition_widgetsDrawer_enterFrom : ''"
:leaveToClass="prefer.s.animation ? $style.transition_widgetsDrawer_leaveTo : ''"
>
<div v-if="widgetsShowing" :class="$style.widgetsDrawer">
<button class="_button" :class="$style.widgetsCloseButton" @click="widgetsShowing = false"><i class="ti ti-x"></i></button>
<XWidgets/>
</div>
</Transition>
<XCommon/>
</div> </div>
</template> </template>
@ -32,6 +85,7 @@ import { instanceName } from '@@/js/config.js';
import { isLink } from '@@/js/is-link.js'; import { isLink } from '@@/js/is-link.js';
import XCommon from './_common_/common.vue'; import XCommon from './_common_/common.vue';
import type { PageMetadata } from '@/page.js'; import type { PageMetadata } from '@/page.js';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue'; import XMobileFooterMenu from '@/ui/_common_/mobile-footer-menu.vue';
import XPreferenceRestore from '@/ui/_common_/PreferenceRestore.vue'; import XPreferenceRestore from '@/ui/_common_/PreferenceRestore.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
@ -124,6 +178,50 @@ const onContextmenu = (ev) => {
$ui-font-size: 1em; // TODO: $ui-font-size: 1em; // TODO:
$widgets-hide-threshold: 1090px; $widgets-hide-threshold: 1090px;
.transition_menuDrawerBg_enterActive,
.transition_menuDrawerBg_leaveActive {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_menuDrawerBg_enterFrom,
.transition_menuDrawerBg_leaveTo {
opacity: 0;
}
.transition_menuDrawer_enterActive,
.transition_menuDrawer_leaveActive {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_menuDrawer_enterFrom,
.transition_menuDrawer_leaveTo {
opacity: 0;
transform: translateX(-240px);
}
.transition_widgetsDrawerBg_enterActive,
.transition_widgetsDrawerBg_leaveActive {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_widgetsDrawerBg_enterFrom,
.transition_widgetsDrawerBg_leaveTo {
opacity: 0;
}
.transition_widgetsDrawer_enterActive,
.transition_widgetsDrawer_leaveActive {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.transition_widgetsDrawer_enterFrom,
.transition_widgetsDrawer_leaveTo {
opacity: 0;
transform: translateX(-240px);
}
.root { .root {
height: 100dvh; height: 100dvh;
overflow: clip; overflow: clip;
@ -150,6 +248,24 @@ $widgets-hide-threshold: 1090px;
min-height: 0; min-height: 0;
} }
.menuDrawerBg {
z-index: 1001;
}
.menuDrawer {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
height: 100dvh;
width: 240px;
box-sizing: border-box;
contain: strict;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-navBg);
}
.statusbars { .statusbars {
position: sticky; position: sticky;
top: 0; top: 0;
@ -169,4 +285,34 @@ $widgets-hide-threshold: 1090px;
display: none; display: none;
} }
} }
.widgetsDrawerBg {
z-index: 1001;
}
.widgetsDrawer {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: 310px;
height: 100dvh;
padding: var(--MI-margin) var(--MI-margin) calc(var(--MI-margin) + env(safe-area-inset-bottom, 0px)) !important;
box-sizing: border-box;
overflow: auto;
overscroll-behavior: contain;
background: var(--MI_THEME-bg);
}
.widgetsCloseButton {
padding: 8px;
display: block;
margin: 0 auto;
}
@media (min-width: 370px) {
.widgetsCloseButton {
display: none;
}
}
</style> </style>

View File

@ -6,14 +6,16 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.root"> <div :class="$style.root">
<div :class="$style.contents"> <div :class="$style.contents">
<div style="flex: 1; min-height: 0;">
<RouterView/>
</div>
<!-- <!--
デッキUIが設定されている場合はデッキUIに戻れるようにする (ただし?zenが明示された場合は表示しない) デッキUIが設定されている場合はデッキUIに戻れるようにする (ただし?zenが明示された場合は表示しない)
See https://github.com/misskey-dev/misskey/issues/10905 See https://github.com/misskey-dev/misskey/issues/10905
--> -->
<button v-if="showDeckNav" class="_buttonPrimary" :class="$style.deckNav" @click="goToDeck">{{ i18n.ts.goToDeck }}</button> <div v-if="showBottom" :class="$style.bottom">
<button v-tooltip="i18n.ts.goToMisskey" :class="['_button', '_shadow', $style.button]" @click="goToMisskey"><i class="ti ti-home"></i></button>
<div style="flex: 1; min-height: 0;">
<RouterView/>
</div> </div>
</div> </div>
@ -35,7 +37,7 @@ const isRoot = computed(() => mainRouter.currentRoute.value.name === 'index');
const pageMetadata = ref<null | PageMetadata>(null); const pageMetadata = ref<null | PageMetadata>(null);
const showDeckNav = !(new URLSearchParams(window.location.search)).has('zen') && ui === 'deck'; const showBottom = !(new URLSearchParams(window.location.search)).has('zen') && ui === 'deck';
provide(DI.router, mainRouter); provide(DI.router, mainRouter);
provideMetadataReceiver((metadataGetter) => { provideMetadataReceiver((metadataGetter) => {
@ -51,7 +53,7 @@ provideMetadataReceiver((metadataGetter) => {
}); });
provideReactiveMetadata(pageMetadata); provideReactiveMetadata(pageMetadata);
function goToDeck() { function goToMisskey() {
window.location.href = '/'; window.location.href = '/';
} }
</script> </script>
@ -66,8 +68,10 @@ function goToDeck() {
height: 100dvh; height: 100dvh;
} }
.deckNav { .bottom {
padding: 4px; height: calc(60px + (var(--MI-margin) * 2) + env(safe-area-inset-bottom, 0px));
width: 100%;
margin-top: auto;
} }
.button { .button {

View File

@ -1,7 +1,7 @@
{ {
"type": "module", "type": "module",
"name": "misskey-js", "name": "misskey-js",
"version": "2025.4.0-rc.4", "version": "2025.4.0-rc.3",
"description": "Misskey SDK for JavaScript", "description": "Misskey SDK for JavaScript",
"license": "MIT", "license": "MIT",
"main": "./built/index.js", "main": "./built/index.js",