Merge tag '13.5.6' into io
This commit is contained in:
commit
1cee3d3c83
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -8,6 +8,17 @@
|
||||||
|
|
||||||
You should also include the user name that made the change.
|
You should also include the user name that made the change.
|
||||||
-->
|
-->
|
||||||
|
## 13.5.6 (2023/02/10)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
- 非ログイン時にMiAuthを踏んだ際にMiAuthであることを表示する
|
||||||
|
- /auth/のUIをアップデート
|
||||||
|
- 利用規約同意UIの調整
|
||||||
|
- クロップ時の質問を分かりやすく
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
- fix: prevent clipping audio plyr's tooltip
|
||||||
|
|
||||||
## 13.5.4 (2023/02/09)
|
## 13.5.4 (2023/02/09)
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
|
@ -257,6 +257,8 @@ noMoreHistory: "Kein weiterer Verlauf vorhanden"
|
||||||
startMessaging: "Neuen Chat erstellen"
|
startMessaging: "Neuen Chat erstellen"
|
||||||
nUsersRead: "Von {n} Benutzern gelesen"
|
nUsersRead: "Von {n} Benutzern gelesen"
|
||||||
agreeTo: "Ich stimme {0} zu"
|
agreeTo: "Ich stimme {0} zu"
|
||||||
|
agreeBelow: "Ich stimme Untenstehendem zu"
|
||||||
|
basicNotesBeforeCreateAccount: "Wichtige Infos"
|
||||||
tos: "Nutzungsbedingungen"
|
tos: "Nutzungsbedingungen"
|
||||||
start: "Anfangen"
|
start: "Anfangen"
|
||||||
home: "Startseite"
|
home: "Startseite"
|
||||||
|
@ -862,6 +864,8 @@ failedToFetchAccountInformation: "Benutzerkontoinformationen konnten nicht abgef
|
||||||
rateLimitExceeded: "Versuchsanzahl überschritten"
|
rateLimitExceeded: "Versuchsanzahl überschritten"
|
||||||
cropImage: "Bild zuschneiden"
|
cropImage: "Bild zuschneiden"
|
||||||
cropImageAsk: "Möchtest du das Bild zuschneiden?"
|
cropImageAsk: "Möchtest du das Bild zuschneiden?"
|
||||||
|
cropYes: "Zuschneiden"
|
||||||
|
cropNo: "Unbearbeitet verwenden"
|
||||||
file: "Datei"
|
file: "Datei"
|
||||||
recentNHours: "Letzten {n} Stunden"
|
recentNHours: "Letzten {n} Stunden"
|
||||||
recentNDays: "Letzten {n} Tage"
|
recentNDays: "Letzten {n} Tage"
|
||||||
|
@ -940,6 +944,8 @@ cannotPerformTemporaryDescription: "Diese Aktion ist wegen des Überschreitenes
|
||||||
preset: "Vorlage"
|
preset: "Vorlage"
|
||||||
selectFromPresets: "Aus Vorlagen wählen"
|
selectFromPresets: "Aus Vorlagen wählen"
|
||||||
achievements: "Errungenschaften"
|
achievements: "Errungenschaften"
|
||||||
|
gotInvalidResponseError: "Ungültige Antwort des Servers"
|
||||||
|
gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal."
|
||||||
_achievements:
|
_achievements:
|
||||||
earnedAt: "Freigeschaltet am"
|
earnedAt: "Freigeschaltet am"
|
||||||
_types:
|
_types:
|
||||||
|
@ -1594,12 +1600,15 @@ _permissions:
|
||||||
"read:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge lesen"
|
"read:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge lesen"
|
||||||
"write:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge bearbeiten"
|
"write:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge bearbeiten"
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "Verteilung von App-Berechtigungen"
|
||||||
shareAccess: "Möchtest du „{name}“ authorisieren, auf dieses Benutzerkonto zugreifen zu können?"
|
shareAccess: "Möchtest du „{name}“ authorisieren, auf dieses Benutzerkonto zugreifen zu können?"
|
||||||
shareAccessAsk: "Bist du dir sicher, dass du diese Anwendung authorisieren möchtest, auf dein Benutzerkonto zugreifen zu können?"
|
shareAccessAsk: "Bist du dir sicher, dass du diese Anwendung authorisieren möchtest, auf dein Benutzerkonto zugreifen zu können?"
|
||||||
|
permission: "{name} fordert folgende Berechtigungen"
|
||||||
permissionAsk: "Diese Anwendung fordert folgende Berechtigungen"
|
permissionAsk: "Diese Anwendung fordert folgende Berechtigungen"
|
||||||
pleaseGoBack: "Bitte kehre zur Anwendung zurück"
|
pleaseGoBack: "Bitte kehre zur Anwendung zurück"
|
||||||
callback: "Es wird zur Anwendung zurückgekehrt"
|
callback: "Es wird zur Anwendung zurückgekehrt"
|
||||||
denied: "Zugriff verweigert"
|
denied: "Zugriff verweigert"
|
||||||
|
pleaseLogin: "Bitte logge dich ein, um Apps zu authorisieren."
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "Alle Notizen"
|
all: "Alle Notizen"
|
||||||
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
|
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
|
||||||
|
|
|
@ -257,6 +257,8 @@ noMoreHistory: "There is no further history"
|
||||||
startMessaging: "Start a new chat"
|
startMessaging: "Start a new chat"
|
||||||
nUsersRead: "read by {n}"
|
nUsersRead: "read by {n}"
|
||||||
agreeTo: "I agree to {0}"
|
agreeTo: "I agree to {0}"
|
||||||
|
agreeBelow: "I agree to the below"
|
||||||
|
basicNotesBeforeCreateAccount: "Important notes"
|
||||||
tos: "Terms of Service"
|
tos: "Terms of Service"
|
||||||
start: "Begin"
|
start: "Begin"
|
||||||
home: "Home"
|
home: "Home"
|
||||||
|
@ -862,6 +864,8 @@ failedToFetchAccountInformation: "Could not fetch account information"
|
||||||
rateLimitExceeded: "Rate limit exceeded"
|
rateLimitExceeded: "Rate limit exceeded"
|
||||||
cropImage: "Crop image"
|
cropImage: "Crop image"
|
||||||
cropImageAsk: "Do you want to crop this image?"
|
cropImageAsk: "Do you want to crop this image?"
|
||||||
|
cropYes: "Crop"
|
||||||
|
cropNo: "Use as-is"
|
||||||
file: "File"
|
file: "File"
|
||||||
recentNHours: "Last {n} hours"
|
recentNHours: "Last {n} hours"
|
||||||
recentNDays: "Last {n} days"
|
recentNDays: "Last {n} days"
|
||||||
|
@ -940,6 +944,8 @@ cannotPerformTemporaryDescription: "This action cannot be performed temporarily
|
||||||
preset: "Preset"
|
preset: "Preset"
|
||||||
selectFromPresets: "Choose from presets"
|
selectFromPresets: "Choose from presets"
|
||||||
achievements: "Achievements"
|
achievements: "Achievements"
|
||||||
|
gotInvalidResponseError: "Invalid server response"
|
||||||
|
gotInvalidResponseErrorDescription: "The server may be unreachable or undergoing maintenance. Please try again later."
|
||||||
_achievements:
|
_achievements:
|
||||||
earnedAt: "Unlocked at"
|
earnedAt: "Unlocked at"
|
||||||
_types:
|
_types:
|
||||||
|
@ -1594,12 +1600,15 @@ _permissions:
|
||||||
"read:gallery-likes": "View your list of liked gallery posts"
|
"read:gallery-likes": "View your list of liked gallery posts"
|
||||||
"write:gallery-likes": "Edit your list of liked gallery posts"
|
"write:gallery-likes": "Edit your list of liked gallery posts"
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "Granting application permissions"
|
||||||
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
||||||
shareAccessAsk: "Are you sure you want to authorize this application to access your account?"
|
shareAccessAsk: "Are you sure you want to authorize this application to access your account?"
|
||||||
|
permission: "{name} requests the following permissions"
|
||||||
permissionAsk: "This application requests the following permissions"
|
permissionAsk: "This application requests the following permissions"
|
||||||
pleaseGoBack: "Please go back to the application"
|
pleaseGoBack: "Please go back to the application"
|
||||||
callback: "Returning to the application"
|
callback: "Returning to the application"
|
||||||
denied: "Access denied"
|
denied: "Access denied"
|
||||||
|
pleaseLogin: "Please log in to authorize applications."
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "All notes"
|
all: "All notes"
|
||||||
homeTimeline: "Notes from followed users"
|
homeTimeline: "Notes from followed users"
|
||||||
|
|
|
@ -56,7 +56,7 @@ reply: "Responder"
|
||||||
loadMore: "Ver más"
|
loadMore: "Ver más"
|
||||||
showMore: "Ver más"
|
showMore: "Ver más"
|
||||||
showLess: "Cerrar"
|
showLess: "Cerrar"
|
||||||
youGotNewFollower: "te ha seguido"
|
youGotNewFollower: "ahora te sigue"
|
||||||
receiveFollowRequest: "Recibiste una solicitud de seguimiento"
|
receiveFollowRequest: "Recibiste una solicitud de seguimiento"
|
||||||
followRequestAccepted: "La solicitud de seguimiento fue aceptada"
|
followRequestAccepted: "La solicitud de seguimiento fue aceptada"
|
||||||
mention: "Menciones"
|
mention: "Menciones"
|
||||||
|
@ -257,6 +257,8 @@ noMoreHistory: "El historial se ha acabado"
|
||||||
startMessaging: "Iniciar chat"
|
startMessaging: "Iniciar chat"
|
||||||
nUsersRead: "Leído por {n} personas"
|
nUsersRead: "Leído por {n} personas"
|
||||||
agreeTo: "De acuerdo con {0}"
|
agreeTo: "De acuerdo con {0}"
|
||||||
|
agreeBelow: "Estoy de acuerdo con lo siguiente"
|
||||||
|
basicNotesBeforeCreateAccount: "Notas básicas"
|
||||||
tos: "Términos de uso"
|
tos: "Términos de uso"
|
||||||
start: "Comenzar"
|
start: "Comenzar"
|
||||||
home: "Inicio"
|
home: "Inicio"
|
||||||
|
@ -940,6 +942,8 @@ cannotPerformTemporaryDescription: "Esta acción no se puede realizar porque se
|
||||||
preset: "Predefinido"
|
preset: "Predefinido"
|
||||||
selectFromPresets: "Escoger desde predefinidos"
|
selectFromPresets: "Escoger desde predefinidos"
|
||||||
achievements: "Logros"
|
achievements: "Logros"
|
||||||
|
gotInvalidResponseError: "Respuesta del servidor inválida"
|
||||||
|
gotInvalidResponseErrorDescription: "Puede que el servidor esté caído o en mantenimiento. Favor de intentar más tarde"
|
||||||
_achievements:
|
_achievements:
|
||||||
earnedAt: "Desbloqueado el"
|
earnedAt: "Desbloqueado el"
|
||||||
_types:
|
_types:
|
||||||
|
@ -1594,12 +1598,15 @@ _permissions:
|
||||||
"read:gallery-likes": "Ver favoritos de la galería"
|
"read:gallery-likes": "Ver favoritos de la galería"
|
||||||
"write:gallery-likes": "Editar favoritos de la galería"
|
"write:gallery-likes": "Editar favoritos de la galería"
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "Permisos de la aplicación"
|
||||||
shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?"
|
shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?"
|
||||||
shareAccessAsk: "¿Está seguro de que desea autorizar esta aplicación para acceder a su cuenta?"
|
shareAccessAsk: "¿Está seguro de que desea autorizar esta aplicación para acceder a su cuenta?"
|
||||||
|
permission: "{name} solicita los siguientes permisos"
|
||||||
permissionAsk: "Esta aplicación requiere los siguientes permisos"
|
permissionAsk: "Esta aplicación requiere los siguientes permisos"
|
||||||
pleaseGoBack: "Por favor, vuelve a la aplicación"
|
pleaseGoBack: "Por favor, vuelve a la aplicación"
|
||||||
callback: "Volviendo a la aplicación"
|
callback: "Volviendo a la aplicación"
|
||||||
denied: "Acceso denegado"
|
denied: "Acceso denegado"
|
||||||
|
pleaseLogin: "Se requiere un inicio de sesión para darle permisos a la aplicación"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "Todas las notas"
|
all: "Todas las notas"
|
||||||
homeTimeline: "Notas de los usuarios que sigues"
|
homeTimeline: "Notas de los usuarios que sigues"
|
||||||
|
|
|
@ -257,6 +257,8 @@ noMoreHistory: "これより過去の履歴はありません"
|
||||||
startMessaging: "チャットを開始"
|
startMessaging: "チャットを開始"
|
||||||
nUsersRead: "{n}人が読みました"
|
nUsersRead: "{n}人が読みました"
|
||||||
agreeTo: "{0}に同意"
|
agreeTo: "{0}に同意"
|
||||||
|
agreeBelow: "下記に同意する"
|
||||||
|
basicNotesBeforeCreateAccount: "基本的な注意事項"
|
||||||
tos: "利用規約"
|
tos: "利用規約"
|
||||||
start: "始める"
|
start: "始める"
|
||||||
home: "ホーム"
|
home: "ホーム"
|
||||||
|
@ -862,6 +864,8 @@ failedToFetchAccountInformation: "アカウント情報の取得に失敗しま
|
||||||
rateLimitExceeded: "レート制限を超えました"
|
rateLimitExceeded: "レート制限を超えました"
|
||||||
cropImage: "画像のクロップ"
|
cropImage: "画像のクロップ"
|
||||||
cropImageAsk: "画像をクロップしますか?"
|
cropImageAsk: "画像をクロップしますか?"
|
||||||
|
cropYes: "クロップする"
|
||||||
|
cropNo: "そのまま使う"
|
||||||
file: "ファイル"
|
file: "ファイル"
|
||||||
recentNHours: "直近{n}時間"
|
recentNHours: "直近{n}時間"
|
||||||
recentNDays: "直近{n}日"
|
recentNDays: "直近{n}日"
|
||||||
|
@ -1628,12 +1632,15 @@ _permissions:
|
||||||
"write:gallery-likes": "ギャラリーのいいねを操作する"
|
"write:gallery-likes": "ギャラリーのいいねを操作する"
|
||||||
|
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "アプリへのアクセス許可"
|
||||||
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"
|
shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?"
|
||||||
shareAccessAsk: "アカウントへのアクセスを許可しますか?"
|
shareAccessAsk: "アカウントへのアクセスを許可しますか?"
|
||||||
|
permission: "{name}は次の権限を要求しています"
|
||||||
permissionAsk: "このアプリは次の権限を要求しています"
|
permissionAsk: "このアプリは次の権限を要求しています"
|
||||||
pleaseGoBack: "アプリケーションに戻ってやっていってください"
|
pleaseGoBack: "アプリケーションに戻ってやっていってください"
|
||||||
callback: "アプリケーションに戻っています"
|
callback: "アプリケーションに戻っています"
|
||||||
denied: "アクセスを拒否しました"
|
denied: "アクセスを拒否しました"
|
||||||
|
pleaseLogin: "アプリケーションにアクセス許可を与えるには、ログインが必要です。"
|
||||||
|
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "全てのノート"
|
all: "全てのノート"
|
||||||
|
|
|
@ -46,7 +46,7 @@ copyContent: "内容をコピー"
|
||||||
copyLink: "リンクをコピー"
|
copyLink: "リンクをコピー"
|
||||||
delete: "ほかす"
|
delete: "ほかす"
|
||||||
deleteAndEdit: "ほかして直す"
|
deleteAndEdit: "ほかして直す"
|
||||||
deleteAndEditConfirm: "このノートをほかして書き直すんか?このノートへのリアクション、Renote、返信も全部消えてまうで。"
|
deleteAndEditConfirm: "このノートをほかしてもっかい直す?このノートへのリアクション、Renote、返信も全部消えるんやけどそれでもええん?"
|
||||||
addToList: "リストに入れたる"
|
addToList: "リストに入れたる"
|
||||||
sendMessage: "メッセージを送る"
|
sendMessage: "メッセージを送る"
|
||||||
copyRSS: "RSSをコピー"
|
copyRSS: "RSSをコピー"
|
||||||
|
@ -89,7 +89,7 @@ serverIsDead: "サーバーからの応答がないで。もうちょい待っ
|
||||||
youShouldUpgradeClient: "このページを表示するには、リロードして新しいバージョンのクライアントを使ってなー。"
|
youShouldUpgradeClient: "このページを表示するには、リロードして新しいバージョンのクライアントを使ってなー。"
|
||||||
enterListName: "リスト名を入れてや"
|
enterListName: "リスト名を入れてや"
|
||||||
privacy: "プライバシー"
|
privacy: "プライバシー"
|
||||||
makeFollowManuallyApprove: "自分が認めた人だけがこのアカウントをフォローできるようにする"
|
makeFollowManuallyApprove: "他人のフォローは許可してからや!"
|
||||||
defaultNoteVisibility: "もとからの公開範囲"
|
defaultNoteVisibility: "もとからの公開範囲"
|
||||||
follow: "フォロー"
|
follow: "フォロー"
|
||||||
followRequest: "フォローを頼む"
|
followRequest: "フォローを頼む"
|
||||||
|
@ -129,6 +129,7 @@ unblockConfirm: "ブロックやめたるってほんまか?"
|
||||||
suspendConfirm: "凍結してしもうてええか?"
|
suspendConfirm: "凍結してしもうてええか?"
|
||||||
unsuspendConfirm: "解凍するけどええか?"
|
unsuspendConfirm: "解凍するけどええか?"
|
||||||
selectList: "リストを選ぶ"
|
selectList: "リストを選ぶ"
|
||||||
|
selectChannel: "チャンネルを選ぶ"
|
||||||
selectAntenna: "アンテナを選ぶ"
|
selectAntenna: "アンテナを選ぶ"
|
||||||
selectWidget: "ウィジェットを選ぶ"
|
selectWidget: "ウィジェットを選ぶ"
|
||||||
editWidgets: "ウィジェットをいじる"
|
editWidgets: "ウィジェットをいじる"
|
||||||
|
@ -256,6 +257,8 @@ noMoreHistory: "これより過去の履歴はあらへんで"
|
||||||
startMessaging: "チャットやるで"
|
startMessaging: "チャットやるで"
|
||||||
nUsersRead: "{n}人が読んでもうた"
|
nUsersRead: "{n}人が読んでもうた"
|
||||||
agreeTo: "{0}に同意したで"
|
agreeTo: "{0}に同意したで"
|
||||||
|
agreeBelow: "下記に同意したる"
|
||||||
|
basicNotesBeforeCreateAccount: "よう読んでやってや"
|
||||||
tos: "利用規約"
|
tos: "利用規約"
|
||||||
start: "始める"
|
start: "始める"
|
||||||
home: "ホーム"
|
home: "ホーム"
|
||||||
|
@ -300,7 +303,7 @@ avatar: "アイコン"
|
||||||
banner: "バナー"
|
banner: "バナー"
|
||||||
nsfw: "閲覧注意"
|
nsfw: "閲覧注意"
|
||||||
whenServerDisconnected: "サーバーとの接続が切れたとき"
|
whenServerDisconnected: "サーバーとの接続が切れたとき"
|
||||||
disconnectedFromServer: "サーバーとの通信が切れたで"
|
disconnectedFromServer: "サーバーが機嫌悪いねん"
|
||||||
reload: "リロード"
|
reload: "リロード"
|
||||||
doNothing: "何もせんとく"
|
doNothing: "何もせんとく"
|
||||||
reloadConfirm: "リロードしてええか?"
|
reloadConfirm: "リロードしてええか?"
|
||||||
|
@ -673,8 +676,8 @@ sentReactionsCount: "リアクションした数やで"
|
||||||
receivedReactionsCount: "リアクションされた数"
|
receivedReactionsCount: "リアクションされた数"
|
||||||
pollVotesCount: "アンケートに投票した数"
|
pollVotesCount: "アンケートに投票した数"
|
||||||
pollVotedCount: "アンケートに投票された数"
|
pollVotedCount: "アンケートに投票された数"
|
||||||
yes: "はい"
|
yes: "ええで"
|
||||||
no: "いいえ"
|
no: "あかんで"
|
||||||
driveFilesCount: "ドライブのファイル数"
|
driveFilesCount: "ドライブのファイル数"
|
||||||
driveUsage: "ドライブ使用量やで"
|
driveUsage: "ドライブ使用量やで"
|
||||||
noCrawle: "クローラーによるインデックスを拒否するで"
|
noCrawle: "クローラーによるインデックスを拒否するで"
|
||||||
|
@ -861,6 +864,8 @@ failedToFetchAccountInformation: "アカウントの取得に失敗したみた
|
||||||
rateLimitExceeded: "レート制限が超えたみたいやで"
|
rateLimitExceeded: "レート制限が超えたみたいやで"
|
||||||
cropImage: "画像のクロップ"
|
cropImage: "画像のクロップ"
|
||||||
cropImageAsk: "画像をクロップしたってええか?"
|
cropImageAsk: "画像をクロップしたってええか?"
|
||||||
|
cropYes: "切り抜いたる"
|
||||||
|
cropNo: "切り抜かへん"
|
||||||
file: "ファイル"
|
file: "ファイル"
|
||||||
recentNHours: "直近{n}時間"
|
recentNHours: "直近{n}時間"
|
||||||
recentNDays: "直近{n}日"
|
recentNDays: "直近{n}日"
|
||||||
|
@ -938,6 +943,37 @@ cannotPerformTemporary: "一時的に利用できへんで"
|
||||||
cannotPerformTemporaryDescription: "操作回数が制限を超えたから一時的に利用できへんくなったで。ちょっと時間置いてからもう一回やってやー。"
|
cannotPerformTemporaryDescription: "操作回数が制限を超えたから一時的に利用できへんくなったで。ちょっと時間置いてからもう一回やってやー。"
|
||||||
preset: "プリセット"
|
preset: "プリセット"
|
||||||
selectFromPresets: "プリセットから選ぶ"
|
selectFromPresets: "プリセットから選ぶ"
|
||||||
|
achievements: "実績"
|
||||||
|
gotInvalidResponseError: "サーバー黙っとるわ、知らんけど"
|
||||||
|
gotInvalidResponseErrorDescription: "サーバーいま日曜日。またきて月曜日。"
|
||||||
|
_achievements:
|
||||||
|
earnedAt: "貰った日ぃ"
|
||||||
|
_types:
|
||||||
|
_notes1:
|
||||||
|
title: "まいど!"
|
||||||
|
description: "初めてノート投稿したった"
|
||||||
|
_notes10:
|
||||||
|
title: "ノートの天保山"
|
||||||
|
_notes100:
|
||||||
|
title: "ノートの真田山"
|
||||||
|
_notes500:
|
||||||
|
title: "ノートの生駒山"
|
||||||
|
_notes5000:
|
||||||
|
title: "箕面の滝からノート"
|
||||||
|
_login3:
|
||||||
|
flavor: "今日からワシはミスキストやで"
|
||||||
|
_iLoveMisskey:
|
||||||
|
title: "Misskey好きやねん"
|
||||||
|
_foundTreasure:
|
||||||
|
title: "なんでも鑑定団"
|
||||||
|
_client30min:
|
||||||
|
title: "ねんね"
|
||||||
|
_noteDeletedWithin1min:
|
||||||
|
title: "*おおっと*"
|
||||||
|
_open3windows:
|
||||||
|
title: "マド開けすぎ"
|
||||||
|
_driveFolderCircularReference:
|
||||||
|
title: "環状線"
|
||||||
_role:
|
_role:
|
||||||
new: "ロールの作成"
|
new: "ロールの作成"
|
||||||
edit: "ロールの編集"
|
edit: "ロールの編集"
|
||||||
|
@ -1355,10 +1391,12 @@ _permissions:
|
||||||
_auth:
|
_auth:
|
||||||
shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?"
|
shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?"
|
||||||
shareAccessAsk: "アカウントのアクセスを許可してもええか?"
|
shareAccessAsk: "アカウントのアクセスを許可してもええか?"
|
||||||
|
permission: "{name}に次の権限つけたってやって"
|
||||||
permissionAsk: "このアプリは次の権限を要求しとるで"
|
permissionAsk: "このアプリは次の権限を要求しとるで"
|
||||||
pleaseGoBack: "アプリケーションに戻ってええよ"
|
pleaseGoBack: "アプリケーションに戻ってええよ"
|
||||||
callback: "アプリケーションに戻っとるで"
|
callback: "アプリケーションに戻っとるで"
|
||||||
denied: "アクセスを拒否ったで"
|
denied: "アクセスを拒否ったで"
|
||||||
|
pleaseLogin: "アプリにアクセスさせるんやったら、ログインしてや。"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "みんなのノート"
|
all: "みんなのノート"
|
||||||
homeTimeline: "フォローしとるユーザーのノート"
|
homeTimeline: "フォローしとるユーザーのノート"
|
||||||
|
@ -1587,6 +1625,7 @@ _notification:
|
||||||
pollEnded: "アンケートの結果が出たみたいや"
|
pollEnded: "アンケートの結果が出たみたいや"
|
||||||
unreadAntennaNote: "アンテナ {name}"
|
unreadAntennaNote: "アンテナ {name}"
|
||||||
emptyPushNotificationMessage: "プッシュ通知の更新をしといたで"
|
emptyPushNotificationMessage: "プッシュ通知の更新をしといたで"
|
||||||
|
achievementEarned: "実績を獲得しとるで"
|
||||||
_types:
|
_types:
|
||||||
all: "すべて"
|
all: "すべて"
|
||||||
follow: "フォロー"
|
follow: "フォロー"
|
||||||
|
|
|
@ -99,18 +99,84 @@ followRequestPending: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍ
|
||||||
enterEmoji: "ປ້ອນອີໂມຈິ"
|
enterEmoji: "ປ້ອນອີໂມຈິ"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
unrenote: "ເລີກ Renote"
|
unrenote: "ເລີກ Renote"
|
||||||
|
renoted: "ເກັບບັນທຶກໄວ້"
|
||||||
|
quote: "ລວມຂໍ້ຄວາມອ້າງອີງ"
|
||||||
|
pinnedNote: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
|
||||||
pinned: "ປັກໝຸດໄປຫາໂປຣໄຟລ໌"
|
pinned: "ປັກໝຸດໄປຫາໂປຣໄຟລ໌"
|
||||||
|
you: "ເຈົ້າ"
|
||||||
|
clickToShow: "ກົດເພື່ອສະແດງໃຫ້ເຫັນ"
|
||||||
|
sensitive: "NSFW"
|
||||||
|
add: "ເພີ່ມ"
|
||||||
|
reaction: "ປະຕິກິລິຍາ"
|
||||||
|
reactions: "ປະຕິກິລິຍາ"
|
||||||
|
mute: "ປີດສຽງ"
|
||||||
|
unmute: "ເປີດສຽງ"
|
||||||
|
block: "ບ໋ອກ"
|
||||||
|
unblock: "ຍົກເລີກກາຮົບລັອກ"
|
||||||
|
suspend: "ລະງັບ"
|
||||||
|
unsuspend: "ເຊົາລະງັບ"
|
||||||
|
selectList: "ເລືອກບັນຊີລາຍການ"
|
||||||
|
selectWidget: "ເລືອກວິກເຈັດ"
|
||||||
|
editWidgets: "ແກ້ໄຂ Widget"
|
||||||
|
editWidgetsExit: "ສຳເລັດແລ້ວ"
|
||||||
|
customEmojis: "ອີໂມຈິແບບກຳນົດເອງ"
|
||||||
|
emoji: "ອີໂມຈິ"
|
||||||
|
emojis: "ອີໂມຈິ"
|
||||||
|
emojiName: "ຊື່ Emoji"
|
||||||
|
emojiUrl: "URL ອີໂມຈິ"
|
||||||
|
addEmoji: "ຕື່ມອີໂມຈິ"
|
||||||
|
flagAsBot: "ໝາຍບັນຊີນີ້ເປັນບັອດ"
|
||||||
|
flagAsCat: "ໝາຍບັນຊີນີ້ເປັນແມວ"
|
||||||
|
flagAsCatDescription: "ເປີດໃຊ້ຕົວເລືອກນີ້ເພື່ອໝາຍບັນຊີນີ້ເປັນແມວ"
|
||||||
|
flagShowTimelineReplies: "ສະແດງການຕອບກັບໃນທາມລາຍ"
|
||||||
|
flagShowTimelineRepliesDescription: "ສະແດງການຕອບກັບຂອງຜູ້ໃຊ້ຕໍ່ກັບບັນທຶກຂອງຜູ້ໃຊ້ອື່ນໃນທາມລາຍຖ້າເປີດໃຊ້ງານ"
|
||||||
|
autoAcceptFollowed: "ອະນຸມັດອັດຕະໂນມັດຕາມຄຳຮ້ອງຂໍຈາກຜູ້ໃຊ້ທີ່ທ່ານກຳລັງຕິດຕາມຢູ່"
|
||||||
addAccount: "ເພີ່ມບັນຊີ"
|
addAccount: "ເພີ່ມບັນຊີ"
|
||||||
loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເລັດ"
|
loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເລັດ"
|
||||||
general: "ທົ່ວໄປ"
|
general: "ທົ່ວໄປ"
|
||||||
wallpaper: "ພາບພື້ນຫລັງ"
|
wallpaper: "ພາບພື້ນຫລັງ"
|
||||||
setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ"
|
setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ"
|
||||||
instances: "ອີນສະແຕນ"
|
instances: "ອີນສະແຕນ"
|
||||||
|
instanceInfo: "ອີນສະແຕນ"
|
||||||
statistics: "ສະຖິຕິ"
|
statistics: "ສະຖິຕິ"
|
||||||
clearQueue: "ລ້າງຄິວ"
|
clearQueue: "ລ້າງຄິວ"
|
||||||
clearCachedFiles: "ລຶບລ້າງແຄສ"
|
clearCachedFiles: "ລຶບລ້າງແຄສ"
|
||||||
editProfile: "ແກ້ໄຂໂປຣໄຟລ໌"
|
editProfile: "ແກ້ໄຂໂປຣໄຟລ໌"
|
||||||
|
done: "ສຳເລັດ"
|
||||||
|
processing: "ກຳລັງປະມວນຜົນ"
|
||||||
|
preview: "ສະແດງເປັນຕົວຢ່າງ"
|
||||||
|
default: "ຄ່າເລີ່ມຕົ້ນ"
|
||||||
|
blocked: "ບລັອກແລ້ວ "
|
||||||
|
all: "ທັງໝົດ"
|
||||||
|
subscribing: "ສະໝັກສະມາຊິກແລັວ"
|
||||||
|
publishing: "ການພິມເຜີຍແຜ່"
|
||||||
|
notResponding: "ບໍ່ຕອບສະໜອງ"
|
||||||
|
instanceFollowing: "ກຳລັງຕິດຕາມສຸດຕົວຢ່າງ"
|
||||||
|
instanceFollowers: "ຜູ້ຕິດຕາມຕົວຢ່າງ"
|
||||||
|
instanceUsers: "ຜູ້ຊົມໃຊ້ຂອງຕົວຢ່າງນີ້"
|
||||||
|
changePassword: "ປ່ຽນລະຫັດຜ່ານ"
|
||||||
|
featured: "ໄຮໄລທ໌"
|
||||||
|
announcements: "ປະກາດ"
|
||||||
remove: "ລຶບ"
|
remove: "ລຶບ"
|
||||||
|
messaging: "ແຊ໋ດ"
|
||||||
|
tos: "ເງື່ອນໄຂການໃຫ້ບໍລິການ"
|
||||||
|
start: "ເລີ່ມຕົ້ນນຳໃຊ້ເລີຍ"
|
||||||
|
home: "ໜ້າຫຼັກ"
|
||||||
|
images: "ຮູບພາບ"
|
||||||
|
birthday: "ວັນເກີດ"
|
||||||
|
registeredDate: "ວັນທີ່ເປັນສະມາຊິກ"
|
||||||
|
location: "ທີ່ຕັ້ງ"
|
||||||
|
theme: "ແທ໋ມ"
|
||||||
|
light: "ສະຫວ່າງ"
|
||||||
|
dark: "ມືດ"
|
||||||
|
lightThemes: "ຊຸດຮູບແບບສະຫວ່າງ"
|
||||||
|
darkThemes: "ຮູບແບບສີສັນມືດ"
|
||||||
|
fileName: "ຊື່ໄຟລ໌"
|
||||||
|
selectFile: "ເລືອກໄຟລ໌"
|
||||||
|
selectFiles: "ເລືອກໄຟລ໌"
|
||||||
|
nsfw: "NSFW"
|
||||||
|
accept: "ອະນຸຍາດ"
|
||||||
|
pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
|
||||||
userList: "ລາຍການ"
|
userList: "ລາຍການ"
|
||||||
smtpUser: "ຊື່ຜູ້ໃຊ້"
|
smtpUser: "ຊື່ຜູ້ໃຊ້"
|
||||||
smtpPass: "ລະຫັດຜ່ານ"
|
smtpPass: "ລະຫັດຜ່ານ"
|
||||||
|
@ -123,6 +189,8 @@ _email:
|
||||||
title: "ໄດ້ຕິດຕາມທ່ານ"
|
title: "ໄດ້ຕິດຕາມທ່ານ"
|
||||||
_mfm:
|
_mfm:
|
||||||
mention: "ໄດ້ກ່າວມາ"
|
mention: "ໄດ້ກ່າວມາ"
|
||||||
|
quote: "ລວມຂໍ້ຄວາມອ້າງອີງ"
|
||||||
|
emoji: "ອີໂມຈິແບບກຳນົດເອງ"
|
||||||
search: "ຄົ້ນຫາ"
|
search: "ຄົ້ນຫາ"
|
||||||
_theme:
|
_theme:
|
||||||
keys:
|
keys:
|
||||||
|
@ -131,25 +199,39 @@ _theme:
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "ບັນທຶກ"
|
note: "ບັນທຶກ"
|
||||||
notification: "ການແຈ້ງເຕືອນ"
|
notification: "ການແຈ້ງເຕືອນ"
|
||||||
|
chat: "ແຊ໋ດ"
|
||||||
_widgets:
|
_widgets:
|
||||||
profile: "ໂພຼຟາຍ"
|
profile: "ໂພຼຟາຍ"
|
||||||
|
instanceInfo: "ອີນສະແຕນ"
|
||||||
notifications: "ການແຈ້ງເຕືອນ"
|
notifications: "ການແຈ້ງເຕືອນ"
|
||||||
timeline: "ເສັ້ນກຳນົດເວລາ"
|
timeline: "ເສັ້ນກຳນົດເວລາ"
|
||||||
|
_userList:
|
||||||
|
chooseList: "ເລືອກບັນຊີລາຍການ"
|
||||||
_cw:
|
_cw:
|
||||||
show: "ໂຫຼດເພີ່ມເຕີມ"
|
show: "ໂຫຼດເພີ່ມເຕີມ"
|
||||||
_visibility:
|
_visibility:
|
||||||
|
home: "ໜ້າຫຼັກ"
|
||||||
followers: "ຜູ້ຕິດຕາມ"
|
followers: "ຜູ້ຕິດຕາມ"
|
||||||
_profile:
|
_profile:
|
||||||
username: "ຊື່ຜູ້ໃຊ້"
|
username: "ຊື່ຜູ້ໃຊ້"
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
followingList: "ກຳລັງຕິດຕາມ"
|
followingList: "ກຳລັງຕິດຕາມ"
|
||||||
|
muteList: "ປີດສຽງ"
|
||||||
|
blockingList: "ບ໋ອກ"
|
||||||
userLists: "ລາຍການ"
|
userLists: "ລາຍການ"
|
||||||
|
_timelines:
|
||||||
|
home: "ໜ້າຫຼັກ"
|
||||||
|
_pages:
|
||||||
|
blocks:
|
||||||
|
image: "ຮູບພາບ"
|
||||||
_notification:
|
_notification:
|
||||||
youWereFollowed: "ໄດ້ຕິດຕາມທ່ານ"
|
youWereFollowed: "ໄດ້ຕິດຕາມທ່ານ"
|
||||||
_types:
|
_types:
|
||||||
follow: "ກຳລັງຕິດຕາມ"
|
follow: "ກຳລັງຕິດຕາມ"
|
||||||
mention: "ໄດ້ກ່າວມາ"
|
mention: "ໄດ້ກ່າວມາ"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
|
quote: "ລວມຂໍ້ຄວາມອ້າງອີງ"
|
||||||
|
reaction: "ປະຕິກິລິຍາ"
|
||||||
_actions:
|
_actions:
|
||||||
reply: "ຕອບໄປທີ"
|
reply: "ຕອບໄປທີ"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
|
|
|
@ -940,6 +940,8 @@ cannotPerformTemporaryDescription: "การดําเนินการน
|
||||||
preset: "พรีเซ็ต"
|
preset: "พรีเซ็ต"
|
||||||
selectFromPresets: "เลือกจากการพรีเซ็ต"
|
selectFromPresets: "เลือกจากการพรีเซ็ต"
|
||||||
achievements: "ความสำเร็จ"
|
achievements: "ความสำเร็จ"
|
||||||
|
gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง"
|
||||||
|
gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ"
|
||||||
_achievements:
|
_achievements:
|
||||||
earnedAt: "ได้รับเมื่อ"
|
earnedAt: "ได้รับเมื่อ"
|
||||||
_types:
|
_types:
|
||||||
|
@ -1594,12 +1596,15 @@ _permissions:
|
||||||
"read:gallery-likes": "ดูรายการโพสต์ในแกลเลอรีที่ชอบของคุณ"
|
"read:gallery-likes": "ดูรายการโพสต์ในแกลเลอรีที่ชอบของคุณ"
|
||||||
"write:gallery-likes": "แก้ไขรายการโพสต์ในแกลเลอรีที่ชอบของคุณ"
|
"write:gallery-likes": "แก้ไขรายการโพสต์ในแกลเลอรีที่ชอบของคุณ"
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "การให้สิทธิ์แอปพลิเคชัน"
|
||||||
shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?"
|
shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?"
|
||||||
shareAccessAsk: "คุณแน่ใจแล้วจริงๆหรอว่าต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณแน่ใจแล้วหรอ?"
|
shareAccessAsk: "คุณแน่ใจแล้วจริงๆหรอว่าต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณแน่ใจแล้วหรอ?"
|
||||||
|
permission: "{name} ได้ขอสิทธิ์การเข้าถึงดังต่อไปนี้"
|
||||||
permissionAsk: "แอปพลิเคชันนี้ขอสิทธิ์ดังต่อไปนี้"
|
permissionAsk: "แอปพลิเคชันนี้ขอสิทธิ์ดังต่อไปนี้"
|
||||||
pleaseGoBack: "กรุณากลับไปที่แอปพลิเคชัน"
|
pleaseGoBack: "กรุณากลับไปที่แอปพลิเคชัน"
|
||||||
callback: "กำลังกลับไปที่แอปพลิเคชัน"
|
callback: "กำลังกลับไปที่แอปพลิเคชัน"
|
||||||
denied: "ปฏิเสธการเข้าใช้"
|
denied: "ปฏิเสธการเข้าใช้"
|
||||||
|
pleaseLogin: "กรุณาเข้าสู่ระบบเพื่ออนุมัติแอปพลิเคชัน"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "โน้ตทั้งหมด"
|
all: "โน้ตทั้งหมด"
|
||||||
homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม"
|
homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม"
|
||||||
|
|
|
@ -129,6 +129,7 @@ unblockConfirm: "确定要解除拉黑吗?"
|
||||||
suspendConfirm: "要冻结吗?"
|
suspendConfirm: "要冻结吗?"
|
||||||
unsuspendConfirm: "要解除冻结吗?"
|
unsuspendConfirm: "要解除冻结吗?"
|
||||||
selectList: "选择列表"
|
selectList: "选择列表"
|
||||||
|
selectChannel: "选择频道"
|
||||||
selectAntenna: "选择天线"
|
selectAntenna: "选择天线"
|
||||||
selectWidget: "选择小工具"
|
selectWidget: "选择小工具"
|
||||||
editWidgets: "编辑部件"
|
editWidgets: "编辑部件"
|
||||||
|
@ -256,6 +257,8 @@ noMoreHistory: "没有更多的历史记录"
|
||||||
startMessaging: "添加聊天"
|
startMessaging: "添加聊天"
|
||||||
nUsersRead: "{n}人已读"
|
nUsersRead: "{n}人已读"
|
||||||
agreeTo: "勾选则表示已阅读并同意{0}"
|
agreeTo: "勾选则表示已阅读并同意{0}"
|
||||||
|
agreeBelow: "同意以下观点"
|
||||||
|
basicNotesBeforeCreateAccount: "基本注意事项"
|
||||||
tos: "服务条款"
|
tos: "服务条款"
|
||||||
start: "开始"
|
start: "开始"
|
||||||
home: "首页"
|
home: "首页"
|
||||||
|
@ -861,6 +864,8 @@ failedToFetchAccountInformation: "获取账户信息失败"
|
||||||
rateLimitExceeded: "已超過速率限制"
|
rateLimitExceeded: "已超過速率限制"
|
||||||
cropImage: "剪裁图像"
|
cropImage: "剪裁图像"
|
||||||
cropImageAsk: "是否要裁剪图像?"
|
cropImageAsk: "是否要裁剪图像?"
|
||||||
|
cropYes: "已裁剪"
|
||||||
|
cropNo: "就这样吧!"
|
||||||
file: "文件"
|
file: "文件"
|
||||||
recentNHours: "最近{n}小时"
|
recentNHours: "最近{n}小时"
|
||||||
recentNDays: "最近{n}天"
|
recentNDays: "最近{n}天"
|
||||||
|
@ -939,6 +944,8 @@ cannotPerformTemporaryDescription: "因操作过于频繁,暂时不可用,
|
||||||
preset: "預設值"
|
preset: "預設值"
|
||||||
selectFromPresets: "從預設值中選擇"
|
selectFromPresets: "從預設值中選擇"
|
||||||
achievements: "成就"
|
achievements: "成就"
|
||||||
|
gotInvalidResponseError: "服务器无应答"
|
||||||
|
gotInvalidResponseErrorDescription: "您的网络连接可能出现了问题, 或是远程服务器暂时不可用. 请稍后重试。"
|
||||||
_achievements:
|
_achievements:
|
||||||
earnedAt: "达成时间"
|
earnedAt: "达成时间"
|
||||||
_types:
|
_types:
|
||||||
|
@ -1122,7 +1129,7 @@ _achievements:
|
||||||
description: "在0点发布一篇帖子"
|
description: "在0点发布一篇帖子"
|
||||||
flavor: "嘣 嘣 嘣 Biu——!"
|
flavor: "嘣 嘣 嘣 Biu——!"
|
||||||
_selfQuote:
|
_selfQuote:
|
||||||
title: "自我提及"
|
title: "自我引用"
|
||||||
description: "引用了自己的帖子"
|
description: "引用了自己的帖子"
|
||||||
_htl20npm:
|
_htl20npm:
|
||||||
title: "流动的时间线"
|
title: "流动的时间线"
|
||||||
|
@ -1593,12 +1600,15 @@ _permissions:
|
||||||
"read:gallery-likes": "读取喜欢的图片"
|
"read:gallery-likes": "读取喜欢的图片"
|
||||||
"write:gallery-likes": "操作喜欢的图片"
|
"write:gallery-likes": "操作喜欢的图片"
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "应用程序授权许可"
|
||||||
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
|
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
|
||||||
shareAccessAsk: "您确定要授权此应用程序访问您的帐户吗?"
|
shareAccessAsk: "您确定要授权此应用程序访问您的帐户吗?"
|
||||||
|
permission: "{name}需要以下权限"
|
||||||
permissionAsk: "这个应用程序需要以下权限"
|
permissionAsk: "这个应用程序需要以下权限"
|
||||||
pleaseGoBack: "请返回到应用程序"
|
pleaseGoBack: "请返回到应用程序"
|
||||||
callback: "回到应用程序"
|
callback: "回到应用程序"
|
||||||
denied: "拒绝访问"
|
denied: "拒绝访问"
|
||||||
|
pleaseLogin: "在对应用进行授权许可之前,请先登录"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "所有帖子"
|
all: "所有帖子"
|
||||||
homeTimeline: "已关注用户的帖子"
|
homeTimeline: "已关注用户的帖子"
|
||||||
|
|
|
@ -129,6 +129,7 @@ unblockConfirm: "確定解除封鎖此用戶?"
|
||||||
suspendConfirm: "確定凍結此帳號?"
|
suspendConfirm: "確定凍結此帳號?"
|
||||||
unsuspendConfirm: "確定解凍此帳號?"
|
unsuspendConfirm: "確定解凍此帳號?"
|
||||||
selectList: "選擇清單"
|
selectList: "選擇清單"
|
||||||
|
selectChannel: "選擇頻道"
|
||||||
selectAntenna: "選擇天線"
|
selectAntenna: "選擇天線"
|
||||||
selectWidget: "選擇小工具"
|
selectWidget: "選擇小工具"
|
||||||
editWidgets: "編輯小工具"
|
editWidgets: "編輯小工具"
|
||||||
|
@ -256,6 +257,8 @@ noMoreHistory: "沒有更多歷史紀錄"
|
||||||
startMessaging: "開始聊天"
|
startMessaging: "開始聊天"
|
||||||
nUsersRead: "{n}人已讀"
|
nUsersRead: "{n}人已讀"
|
||||||
agreeTo: "我同意{0}"
|
agreeTo: "我同意{0}"
|
||||||
|
agreeBelow: "同意以下內容"
|
||||||
|
basicNotesBeforeCreateAccount: "基本注意事項"
|
||||||
tos: "使用條款"
|
tos: "使用條款"
|
||||||
start: "開始"
|
start: "開始"
|
||||||
home: "首頁"
|
home: "首頁"
|
||||||
|
@ -861,6 +864,8 @@ failedToFetchAccountInformation: "取得帳戶資訊失敗"
|
||||||
rateLimitExceeded: "已超過速率限制"
|
rateLimitExceeded: "已超過速率限制"
|
||||||
cropImage: "圖片裁剪"
|
cropImage: "圖片裁剪"
|
||||||
cropImageAsk: "要剪裁圖片嗎?"
|
cropImageAsk: "要剪裁圖片嗎?"
|
||||||
|
cropYes: "裁剪"
|
||||||
|
cropNo: "使用原圖"
|
||||||
file: "檔案"
|
file: "檔案"
|
||||||
recentNHours: "過去{n}小時"
|
recentNHours: "過去{n}小時"
|
||||||
recentNDays: "過去{n}天"
|
recentNDays: "過去{n}天"
|
||||||
|
@ -1595,12 +1600,15 @@ _permissions:
|
||||||
"read:gallery-likes": "讀取喜歡的圖片"
|
"read:gallery-likes": "讀取喜歡的圖片"
|
||||||
"write:gallery-likes": "操作喜歡的圖片"
|
"write:gallery-likes": "操作喜歡的圖片"
|
||||||
_auth:
|
_auth:
|
||||||
|
shareAccessTitle: "應用程式的存取權限"
|
||||||
shareAccess: "要授權「“{name}”」存取您的帳戶嗎?"
|
shareAccess: "要授權「“{name}”」存取您的帳戶嗎?"
|
||||||
shareAccessAsk: "您確定要授權這個應用程式使用您的帳戶嗎?"
|
shareAccessAsk: "您確定要授權這個應用程式使用您的帳戶嗎?"
|
||||||
|
permission: "{name}要求以下的權限"
|
||||||
permissionAsk: "此應用程式需要以下權限"
|
permissionAsk: "此應用程式需要以下權限"
|
||||||
pleaseGoBack: "請返回至應用程式"
|
pleaseGoBack: "請返回至應用程式"
|
||||||
callback: "回到應用程式"
|
callback: "回到應用程式"
|
||||||
denied: "拒絕訪問"
|
denied: "拒絕訪問"
|
||||||
|
pleaseLogin: "必須登入以提供應用程式的存取權限。"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "全部貼文"
|
all: "全部貼文"
|
||||||
homeTimeline: "來自已追隨使用者的貼文"
|
homeTimeline: "來自已追隨使用者的貼文"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "13.5.5",
|
"version": "13.5.6",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/misskey-dev/misskey.git"
|
"url": "https://github.com/misskey-dev/misskey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@7.24.3",
|
"packageManager": "pnpm@7.27.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/frontend",
|
"packages/frontend",
|
||||||
"packages/backend",
|
"packages/backend",
|
||||||
|
|
|
@ -255,8 +255,21 @@ export class FileServerService {
|
||||||
const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image');
|
const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image');
|
||||||
const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image');
|
const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image');
|
||||||
|
|
||||||
|
if (
|
||||||
|
'emoji' in request.query ||
|
||||||
|
'avatar' in request.query ||
|
||||||
|
'static' in request.query ||
|
||||||
|
'preview' in request.query ||
|
||||||
|
'badge' in request.query
|
||||||
|
) {
|
||||||
|
if (!isConvertibleImage) {
|
||||||
|
// 画像でないなら404でお茶を濁す
|
||||||
|
throw new StatusError('Unexpected mime', 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let image: IImageStreamable | null = null;
|
let image: IImageStreamable | null = null;
|
||||||
if (('emoji' in request.query || 'avatar' in request.query) && isConvertibleImage) {
|
if ('emoji' in request.query || 'avatar' in request.query) {
|
||||||
if (!isAnimationConvertibleImage && !('static' in request.query)) {
|
if (!isAnimationConvertibleImage && !('static' in request.query)) {
|
||||||
image = {
|
image = {
|
||||||
data: fs.createReadStream(file.path),
|
data: fs.createReadStream(file.path),
|
||||||
|
@ -277,16 +290,11 @@ export class FileServerService {
|
||||||
type: 'image/webp',
|
type: 'image/webp',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if ('static' in request.query && isConvertibleImage) {
|
} else if ('static' in request.query) {
|
||||||
image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280);
|
image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280);
|
||||||
} else if ('preview' in request.query && isConvertibleImage) {
|
} else if ('preview' in request.query) {
|
||||||
image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200);
|
image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200);
|
||||||
} else if ('badge' in request.query) {
|
} else if ('badge' in request.query) {
|
||||||
if (!isConvertibleImage) {
|
|
||||||
// 画像でないなら404でお茶を濁す
|
|
||||||
throw new StatusError('Unexpected mime', 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mask = sharp(file.path)
|
const mask = sharp(file.path)
|
||||||
.resize(96, 96, {
|
.resize(96, 96, {
|
||||||
fit: 'inside',
|
fit: 'inside',
|
||||||
|
|
|
@ -107,6 +107,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconFrame {
|
.iconFrame {
|
||||||
|
position: relative;
|
||||||
width: 58px;
|
width: 58px;
|
||||||
height: 58px;
|
height: 58px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<button class="_button" :class="$style.root" @click="toggle">
|
<button class="_button" :class="$style.root" @mousedown="toggle">
|
||||||
<b>{{ modelValue ? i18n.ts._cw.hide : i18n.ts._cw.show }}</b>
|
<b>{{ modelValue ? i18n.ts._cw.hide : i18n.ts._cw.show }}</b>
|
||||||
<span v-if="!modelValue" :class="$style.label">{{ label }}</span>
|
<span v-if="!modelValue" :class="$style.label">{{ label }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
</template>
|
</template>
|
||||||
</MkSelect>
|
</MkSelect>
|
||||||
<div v-if="(showOkButton || showCancelButton) && !actions" :class="$style.buttons">
|
<div v-if="(showOkButton || showCancelButton) && !actions" :class="$style.buttons">
|
||||||
<MkButton v-if="showOkButton" inline primary :autofocus="!input && !select" @click="ok">{{ (showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt }}</MkButton>
|
<MkButton v-if="showOkButton" inline primary :autofocus="!input && !select" @click="ok">{{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }}</MkButton>
|
||||||
<MkButton v-if="showCancelButton || input || select" inline @click="cancel">{{ i18n.ts.cancel }}</MkButton>
|
<MkButton v-if="showCancelButton || input || select" inline @click="cancel">{{ cancelText ?? i18n.ts.cancel }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="actions" :class="$style.buttons">
|
<div v-if="actions" :class="$style.buttons">
|
||||||
<MkButton v-for="action in actions" :key="action.text" inline :primary="action.primary" @click="() => { action.callback(); close(); }">{{ action.text }}</MkButton>
|
<MkButton v-for="action in actions" :key="action.text" inline :primary="action.primary" @click="() => { action.callback(); close(); }">{{ action.text }}</MkButton>
|
||||||
|
@ -82,6 +82,8 @@ const props = withDefaults(defineProps<{
|
||||||
showOkButton?: boolean;
|
showOkButton?: boolean;
|
||||||
showCancelButton?: boolean;
|
showCancelButton?: boolean;
|
||||||
cancelableByBgClick?: boolean;
|
cancelableByBgClick?: boolean;
|
||||||
|
okText?: string;
|
||||||
|
cancelText?: string;
|
||||||
}>(), {
|
}>(), {
|
||||||
type: 'info',
|
type: 'info',
|
||||||
showOkButton: true,
|
showOkButton: true,
|
||||||
|
|
|
@ -56,7 +56,7 @@ onMounted(() => {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
overflow: clip;
|
// overflow: clip;
|
||||||
|
|
||||||
--plyr-color-main: var(--accent);
|
--plyr-color-main: var(--accent);
|
||||||
--plyr-audio-controls-background: var(--bg);
|
--plyr-audio-controls-background: var(--bg);
|
||||||
|
@ -99,7 +99,7 @@ onMounted(() => {
|
||||||
|
|
||||||
> .audio {
|
> .audio {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: clip;
|
// overflow: clip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -50,13 +50,13 @@
|
||||||
<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.passwordNotMatched }}</span>
|
<span v-if="passwordRetypeState == 'not-match'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.passwordNotMatched }}</span>
|
||||||
</template>
|
</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
<MkSwitch v-if="instance.tosUrl" v-model="ToSAgreement" class="tou">
|
<MkSwitch v-model="ToSAgreement" class="tou">
|
||||||
<I18n :src="i18n.ts.agreeTo">
|
<template #label>{{ i18n.ts.agreeBelow }}</template>
|
||||||
<template #0>
|
|
||||||
<a :href="instance.tosUrl" class="_link" target="_blank">{{ i18n.ts.tos }}</a>
|
|
||||||
</template>
|
|
||||||
</I18n>
|
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
|
<ul style="margin: 0; padding-left: 2em;">
|
||||||
|
<li v-if="instance.tosUrl"><a :href="instance.tosUrl" class="_link" target="_blank">{{ i18n.ts.tos }}</a></li>
|
||||||
|
<li><a href="https://misskey-hub.net/docs/notes.html" class="_link" target="_blank">{{ i18n.ts.basicNotesBeforeCreateAccount }}</a></li>
|
||||||
|
</ul>
|
||||||
<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" class="captcha" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/>
|
<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" class="captcha" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/>
|
||||||
<MkCaptcha v-if="instance.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" class="captcha" provider="recaptcha" :sitekey="instance.recaptchaSiteKey"/>
|
<MkCaptcha v-if="instance.enableRecaptcha" ref="recaptcha" v-model="reCaptchaResponse" class="captcha" provider="recaptcha" :sitekey="instance.recaptchaSiteKey"/>
|
||||||
<MkCaptcha v-if="instance.enableTurnstile" ref="turnstile" v-model="turnstileResponse" class="captcha" provider="turnstile" :sitekey="instance.turnstileSiteKey"/>
|
<MkCaptcha v-if="instance.enableTurnstile" ref="turnstile" v-model="turnstileResponse" class="captcha" provider="turnstile" :sitekey="instance.turnstileSiteKey"/>
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
<template>
|
<template>
|
||||||
<span v-if="!link" v-user-preview="preview ? user.id : undefined" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" class="_noSelect" :style="{ color }" :title="acct(user)" @click="onClick">
|
<span v-if="!link" v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick">
|
||||||
<img :class="$style.inner" :src="url" decoding="async"/>
|
<img :class="$style.inner" :src="url" decoding="async"/>
|
||||||
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
||||||
|
<template v-if="user.isCat">
|
||||||
|
<div :class="$style.earLeft"/>
|
||||||
|
<div :class="$style.earRight"/>
|
||||||
|
</template>
|
||||||
</span>
|
</span>
|
||||||
<MkA v-else v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :to="userPage(user)" :title="acct(user)" :target="target">
|
<MkA v-else v-user-preview="preview ? user.id : undefined" class="_noSelect" :class="[$style.root, { [$style.cat]: user.isCat, [$style.square]: $store.state.squareAvatars }]" :style="{ color }" :title="acct(user)" :to="userPage(user)" :target="target">
|
||||||
<img :class="$style.inner" :src="url" decoding="async"/>
|
<img :class="$style.inner" :src="url" decoding="async"/>
|
||||||
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
||||||
|
<template v-if="user.isCat">
|
||||||
|
<div :class="$style.earLeft"/>
|
||||||
|
<div :class="$style.earRight"/>
|
||||||
|
</template>
|
||||||
</MkA>
|
</MkA>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -110,32 +118,41 @@ watch(() => props.user.avatarBlurhash, () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cat {
|
.cat {
|
||||||
&:before, &:after {
|
> .earLeft,
|
||||||
background: #df548f;
|
> .earRight {
|
||||||
border: solid 4px currentColor;
|
contain: strict;
|
||||||
box-sizing: border-box;
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 50%;
|
height: 50%;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
background: currentColor;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
contain: strict;
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 60%;
|
||||||
|
height: 60%;
|
||||||
|
margin: 20%;
|
||||||
|
background: #df548f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:before {
|
> .earLeft {
|
||||||
border-radius: 0 75% 75%;
|
border-radius: 0 75% 75%;
|
||||||
transform: rotate(37.5deg) skew(30deg);
|
transform: rotate(37.5deg) skew(30deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
> .earRight {
|
||||||
border-radius: 75% 0 75% 75%;
|
border-radius: 75% 0 75% 75%;
|
||||||
transform: rotate(-37.5deg) skew(-30deg);
|
transform: rotate(-37.5deg) skew(-30deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
&:before {
|
> .earLeft {
|
||||||
animation: earwiggleleft 1s infinite;
|
animation: earwiggleleft 1s infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
> .earRight {
|
||||||
animation: earwiggleright 1s infinite;
|
animation: earwiggleright 1s infinite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,8 @@ export function confirm(props: {
|
||||||
type: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question';
|
type: 'error' | 'info' | 'success' | 'warning' | 'waiting' | 'question';
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
text?: string | null;
|
text?: string | null;
|
||||||
|
okText?: string;
|
||||||
|
cancelText?: string;
|
||||||
}): Promise<{ canceled: boolean }> {
|
}): Promise<{ canceled: boolean }> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
popup(MkDialog, {
|
popup(MkDialog, {
|
||||||
|
|
|
@ -1,60 +1,66 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="">
|
<section>
|
||||||
<div class="">{{ $t('_auth.shareAccess', { name: app.name }) }}</div>
|
<div v-if="app.permission.length > 0">
|
||||||
<div class="">
|
<p>{{ $t('_auth.permission', { name }) }}</p>
|
||||||
<h2>{{ app.name }}</h2>
|
|
||||||
<p class="id">{{ app.id }}</p>
|
|
||||||
<p class="description">{{ app.description }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="">
|
|
||||||
<h2>{{ $ts._auth.permissionAsk }}</h2>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li>
|
<li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div>{{ i18n.t('_auth.shareAccess', { name: `${name} (${app.id})` }) }}</div>
|
||||||
<MkButton inline @click="cancel">{{ $ts.cancel }}</MkButton>
|
<div :class="$style.buttons">
|
||||||
<MkButton inline primary @click="accept">{{ $ts.accept }}</MkButton>
|
<MkButton inline @click="cancel">{{ i18n.ts.cancel }}</MkButton>
|
||||||
|
<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from 'vue';
|
import { } from 'vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
import { AuthSession } from 'misskey-js/built/entities';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
components: {
|
session: AuthSession;
|
||||||
MkButton,
|
}>();
|
||||||
},
|
|
||||||
props: ['session'],
|
const emit = defineEmits<{
|
||||||
computed: {
|
(event: 'accepted'): void;
|
||||||
name(): string {
|
(event: 'denied'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const app = $computed(() => props.session.app);
|
||||||
|
|
||||||
|
const name = $computed(() => {
|
||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.textContent = this.app.name;
|
el.textContent = app.name;
|
||||||
return el.innerHTML;
|
return el.innerHTML;
|
||||||
},
|
|
||||||
app(): any {
|
|
||||||
return this.session.app;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
cancel() {
|
|
||||||
os.api('auth/deny', {
|
|
||||||
token: this.session.token,
|
|
||||||
}).then(() => {
|
|
||||||
this.$emit('denied');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
accept() {
|
|
||||||
os.api('auth/accept', {
|
|
||||||
token: this.session.token,
|
|
||||||
}).then(() => {
|
|
||||||
this.$emit('accepted');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function cancel() {
|
||||||
|
os.api('auth/deny', {
|
||||||
|
token: props.session.token,
|
||||||
|
}).then(() => {
|
||||||
|
emit('denied');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function accept() {
|
||||||
|
os.api('auth/accept', {
|
||||||
|
token: props.session.token,
|
||||||
|
}).then(() => {
|
||||||
|
emit('accepted');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.buttons {
|
||||||
|
margin-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,93 +1,105 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="$i && fetching" class="">
|
<MkStickyContainer>
|
||||||
<MkLoading/>
|
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template>
|
||||||
</div>
|
<MkSpacer :content-max="500">
|
||||||
<div v-else-if="$i">
|
<div v-if="state == 'fetch-session-error'">
|
||||||
|
<p>{{ i18n.ts.somethingHappened }}</p>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="$i && !session">
|
||||||
|
<MkLoading />
|
||||||
|
</div>
|
||||||
|
<div v-else-if="$i && session">
|
||||||
<XForm
|
<XForm
|
||||||
v-if="state == 'waiting'"
|
v-if="state == 'waiting'"
|
||||||
ref="form"
|
|
||||||
class="form"
|
class="form"
|
||||||
:session="session"
|
:session="session"
|
||||||
@denied="state = 'denied'"
|
@denied="state = 'denied'"
|
||||||
@accepted="accepted"
|
@accepted="accepted"
|
||||||
/>
|
/>
|
||||||
<div v-if="state == 'denied'" class="denied">
|
<div v-if="state == 'denied'">
|
||||||
<h1>{{ $ts._auth.denied }}</h1>
|
<h1>{{ i18n.ts._auth.denied }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="state == 'accepted'" class="accepted">
|
<div v-if="state == 'accepted' && session">
|
||||||
<h1>{{ session.app.isAuthorized ? $t('already-authorized') : $ts.allowed }}</h1>
|
<h1>{{ session.app.isAuthorized ? $t('already-authorized') : i18n.ts.allowed }}</h1>
|
||||||
<p v-if="session.app.callbackUrl">{{ $ts._auth.callback }}<MkEllipsis/></p>
|
<p v-if="session.app.callbackUrl">{{ i18n.ts._auth.callback }}
|
||||||
<p v-if="!session.app.callbackUrl">{{ $ts._auth.pleaseGoBack }}</p>
|
<MkEllipsis />
|
||||||
|
</p>
|
||||||
|
<p v-if="!session.app.callbackUrl">{{ i18n.ts._auth.pleaseGoBack }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="state == 'fetch-session-error'" class="error">
|
|
||||||
<p>{{ $ts.somethingHappened }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div v-else>
|
||||||
<div v-else class="signin">
|
<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p>
|
||||||
<MkSignin @login="onLogin"/>
|
<MkSignin @login="onLogin" />
|
||||||
</div>
|
</div>
|
||||||
|
</MkSpacer>
|
||||||
|
</MkStickyContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent } from 'vue';
|
import { onMounted } from 'vue';
|
||||||
import XForm from './auth.form.vue';
|
import XForm from './auth.form.vue';
|
||||||
import MkSignin from '@/components/MkSignin.vue';
|
import MkSignin from '@/components/MkSignin.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { login } from '@/account';
|
import { $i, login } from '@/account';
|
||||||
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
|
import { AuthSession } from 'misskey-js/built/entities';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
export default defineComponent({
|
const props = defineProps<{
|
||||||
components: {
|
token: string;
|
||||||
XForm,
|
}>();
|
||||||
MkSignin,
|
|
||||||
},
|
|
||||||
props: ['token'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
state: null,
|
|
||||||
session: null,
|
|
||||||
fetching: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (!this.$i) return;
|
|
||||||
|
|
||||||
// Fetch session
|
let state = $ref<'waiting' | 'accepted' | 'fetch-session-error' | 'denied' | null>(null);
|
||||||
os.api('auth/session/show', {
|
let session = $ref<AuthSession | null>(null);
|
||||||
token: this.token,
|
|
||||||
}).then(session => {
|
function accepted() {
|
||||||
this.session = session;
|
state = 'accepted';
|
||||||
this.fetching = false;
|
if (session && session.app.callbackUrl) {
|
||||||
|
const url = new URL(session.app.callbackUrl);
|
||||||
|
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url');
|
||||||
|
location.href = `${session.app.callbackUrl}?token=${session.token}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLogin(res) {
|
||||||
|
login(res.i);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (!$i) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
session = await os.api('auth/session/show', {
|
||||||
|
token: props.token,
|
||||||
|
});
|
||||||
|
|
||||||
// 既に連携していた場合
|
// 既に連携していた場合
|
||||||
if (this.session.app.isAuthorized) {
|
if (session.app.isAuthorized) {
|
||||||
os.api('auth/accept', {
|
await os.api('auth/accept', {
|
||||||
token: this.session.token,
|
token: session.token,
|
||||||
}).then(() => {
|
|
||||||
this.accepted();
|
|
||||||
});
|
});
|
||||||
|
accepted();
|
||||||
} else {
|
} else {
|
||||||
this.state = 'waiting';
|
state = 'waiting';
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
} catch (e) {
|
||||||
this.state = 'fetch-session-error';
|
state = 'fetch-session-error';
|
||||||
this.fetching = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
accepted() {
|
|
||||||
this.state = 'accepted';
|
|
||||||
if (this.session.app.callbackUrl) {
|
|
||||||
const url = new URL(this.session.app.callbackUrl);
|
|
||||||
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url');
|
|
||||||
location.href = `${this.session.app.callbackUrl}?token=${this.session.token}`;
|
|
||||||
}
|
}
|
||||||
}, onLogin(res) {
|
});
|
||||||
login(res.i);
|
|
||||||
},
|
const headerActions = $computed(() => []);
|
||||||
},
|
|
||||||
|
const headerTabs = $computed(() => []);
|
||||||
|
|
||||||
|
definePageMetadata({
|
||||||
|
title: i18n.ts._auth.shareAccessTitle,
|
||||||
|
icon: 'ti ti-apps',
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" module>
|
||||||
|
.loginMessage {
|
||||||
|
text-align: center;
|
||||||
|
margin: 8px 0 24px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,41 +1,40 @@
|
||||||
<template>
|
<template>
|
||||||
<MkSpacer :content-max="800">
|
<MkStickyContainer>
|
||||||
|
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template>
|
||||||
|
<MkSpacer :content-max="800">
|
||||||
<div v-if="$i">
|
<div v-if="$i">
|
||||||
<div v-if="state == 'waiting'" class="waiting">
|
<div v-if="state == 'waiting'">
|
||||||
<div class="">
|
|
||||||
<MkLoading/>
|
<MkLoading/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div v-if="state == 'denied'">
|
||||||
<div v-if="state == 'denied'" class="denied">
|
|
||||||
<div class="">
|
|
||||||
<p>{{ i18n.ts._auth.denied }}</p>
|
<p>{{ i18n.ts._auth.denied }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div v-else-if="state == 'accepted'" class="accepted">
|
<div v-else-if="state == 'accepted'" class="accepted">
|
||||||
<div class="">
|
|
||||||
<p v-if="callback">{{ i18n.ts._auth.callback }}<MkEllipsis/></p>
|
<p v-if="callback">{{ i18n.ts._auth.callback }}<MkEllipsis/></p>
|
||||||
<p v-else>{{ i18n.ts._auth.pleaseGoBack }}</p>
|
<p v-else>{{ i18n.ts._auth.pleaseGoBack }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div v-else>
|
||||||
<div v-else class="">
|
<div v-if="_permissions.length > 0">
|
||||||
<div v-if="name" class="">{{ $t('_auth.shareAccess', { name: name }) }}</div>
|
<p v-if="name">{{ $t('_auth.permission', { name }) }}</p>
|
||||||
<div v-else class="">{{ i18n.ts._auth.shareAccessAsk }}</div>
|
<p v-else>{{ i18n.ts._auth.permissionAsk }}</p>
|
||||||
<div class="">
|
|
||||||
<p>{{ i18n.ts._auth.permissionAsk }}</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li>
|
<li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div v-if="name">{{ $t('_auth.shareAccess', { name }) }}</div>
|
||||||
|
<div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div>
|
||||||
|
<div :class="$style.buttons">
|
||||||
<MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton>
|
<MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton>
|
||||||
<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton>
|
<MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="signin">
|
<div v-else>
|
||||||
|
<p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p>
|
||||||
<MkSignin @login="onLogin"/>
|
<MkSignin @login="onLogin"/>
|
||||||
</div>
|
</div>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
|
</MkStickyContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -45,6 +44,7 @@ import MkButton from '@/components/MkButton.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { $i, login } from '@/account';
|
import { $i, login } from '@/account';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
session: string;
|
session: string;
|
||||||
|
@ -54,7 +54,7 @@ const props = defineProps<{
|
||||||
permission: string; // コンマ区切り
|
permission: string; // コンマ区切り
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const _permissions = props.permission.split(',');
|
const _permissions = props.permission ? props.permission.split(',') : [];
|
||||||
|
|
||||||
let state = $ref<string | null>(null);
|
let state = $ref<string | null>(null);
|
||||||
|
|
||||||
|
@ -83,8 +83,27 @@ function deny(): void {
|
||||||
function onLogin(res): void {
|
function onLogin(res): void {
|
||||||
login(res.i);
|
login(res.i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const headerActions = $computed(() => []);
|
||||||
|
|
||||||
|
const headerTabs = $computed(() => []);
|
||||||
|
|
||||||
|
definePageMetadata({
|
||||||
|
title: 'MiAuth',
|
||||||
|
icon: 'ti ti-apps',
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" module>
|
||||||
|
.buttons {
|
||||||
|
margin-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loginMessage {
|
||||||
|
text-align: center;
|
||||||
|
margin: 8px 0 24px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -150,6 +150,8 @@ function changeAvatar(ev) {
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
type: 'question',
|
type: 'question',
|
||||||
text: i18n.t('cropImageAsk'),
|
text: i18n.t('cropImageAsk'),
|
||||||
|
okText: i18n.ts.cropYes,
|
||||||
|
cancelText: i18n.ts.cropNo,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
|
@ -174,6 +176,8 @@ function changeBanner(ev) {
|
||||||
const { canceled } = await os.confirm({
|
const { canceled } = await os.confirm({
|
||||||
type: 'question',
|
type: 'question',
|
||||||
text: i18n.t('cropImageAsk'),
|
text: i18n.t('cropImageAsk'),
|
||||||
|
okText: i18n.ts.cropYes,
|
||||||
|
cancelText: i18n.ts.cropNo,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<i class="icon ti ti-pencil ti-fw"></i><span class="text">{{ i18n.ts.note }}</span>
|
<i class="icon ti ti-pencil ti-fw"></i><span class="text">{{ i18n.ts.note }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button v-click-anime class="item _button account" @click="openAccountMenu">
|
<button v-click-anime class="item _button account" @click="openAccountMenu">
|
||||||
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
|
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text _nowrap" :user="$i"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -168,20 +168,25 @@ function more() {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 1;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<i class="icon ti ti-pencil ti-fw"></i><span class="text">{{ i18n.ts.note }}</span>
|
<i class="icon ti ti-pencil ti-fw"></i><span class="text">{{ i18n.ts.note }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button v-click-anime v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="item _button account" @click="openAccountMenu">
|
<button v-click-anime v-tooltip.noDelay.right="`${i18n.ts.account}: @${$i.username}`" class="item _button account" @click="openAccountMenu">
|
||||||
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/>
|
<MkAvatar :user="$i" class="avatar"/><MkAcct class="text _nowrap" :user="$i"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -217,20 +217,25 @@ function more(ev: MouseEvent) {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
|
|
||||||
> .avatar {
|
> .avatar {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .text {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 1;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue