mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-05-18 03:17:29 +08:00
feat: 格式化代码
This commit is contained in:
@@ -45,7 +45,8 @@ export default {
|
||||
phoneLoginFailed: 'Phone login failed, please check if phone number and password are correct',
|
||||
autoGetCookieSuccess: 'Auto get Cookie successful',
|
||||
autoGetCookieFailed: 'Auto get Cookie failed',
|
||||
autoGetCookieTip: 'Will open NetEase Cloud Music login page, please complete login and close the window',
|
||||
autoGetCookieTip:
|
||||
'Will open NetEase Cloud Music login page, please complete login and close the window',
|
||||
qrCheckFailed: 'Failed to check QR code status, please refresh and try again',
|
||||
qrLoading: 'Loading QR code...',
|
||||
qrExpired: 'QR code has expired, please click to refresh',
|
||||
@@ -58,5 +59,6 @@ export default {
|
||||
qrGenerating: 'Generating QR code...'
|
||||
},
|
||||
qrTitle: 'NetEase Cloud Music QR Code Login',
|
||||
uidWarning: 'Note: UID login is only for viewing user public information and cannot access features that require login permissions.'
|
||||
uidWarning:
|
||||
'Note: UID login is only for viewing user public information and cannot access features that require login permissions.'
|
||||
};
|
||||
|
||||
@@ -82,7 +82,8 @@ export default {
|
||||
showStatusBarContent:
|
||||
'You can display the music control function in your mac status bar (effective after a restart)',
|
||||
fallbackParser: 'Fallback Parser (GD Music)',
|
||||
fallbackParserDesc: 'When "GD Music" is checked and regular sources fail, this service will be used.',
|
||||
fallbackParserDesc:
|
||||
'When "GD Music" is checked and regular sources fail, this service will be used.',
|
||||
parserGD: 'GD Music (Built-in)',
|
||||
parserCustom: 'Custom API',
|
||||
|
||||
@@ -103,8 +104,8 @@ export default {
|
||||
notImported: 'No custom source imported yet.',
|
||||
importSuccess: 'Successfully imported source: {name}',
|
||||
importFailed: 'Import failed: {message}',
|
||||
enableHint: 'Import a JSON config file to enable',
|
||||
},
|
||||
enableHint: 'Import a JSON config file to enable'
|
||||
}
|
||||
},
|
||||
application: {
|
||||
closeAction: 'Close Action',
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
|
||||
- すべての翻訳キーは中国語版と英語版に対応しています
|
||||
- 新しい機能が追加された場合は、対応する日本語翻訳も追加する必要があります
|
||||
- 文字化けを避けるため、ファイルはUTF-8エンコーディングで保存してください
|
||||
- 文字化けを避けるため、ファイルはUTF-8エンコーディングで保存してください
|
||||
|
||||
@@ -2,4 +2,4 @@ export default {
|
||||
hotSongs: '人気楽曲',
|
||||
albums: 'アルバム',
|
||||
description: 'アーティスト紹介'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -53,4 +53,4 @@ export default {
|
||||
play: '再生',
|
||||
favorite: 'お気に入り'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -38,10 +38,12 @@ export default {
|
||||
nowUpdate: '今すぐ更新',
|
||||
downloadFailed: 'ダウンロードに失敗しました。再試行するか手動でダウンロードしてください',
|
||||
startFailed: 'ダウンロードの開始に失敗しました。再試行するか手動でダウンロードしてください',
|
||||
noDownloadUrl: '現在のシステムに適したインストールパッケージが見つかりません。手動でダウンロードしてください',
|
||||
noDownloadUrl:
|
||||
'現在のシステムに適したインストールパッケージが見つかりません。手動でダウンロードしてください',
|
||||
installConfirmTitle: '更新をインストール',
|
||||
installConfirmContent: 'アプリを閉じて更新をインストールしますか?',
|
||||
manualInstallTip: 'アプリを閉じた後にインストーラーが正常に起動しない場合は、ダウンロードフォルダでファイルを見つけて手動で開いてください。',
|
||||
manualInstallTip:
|
||||
'アプリを閉じた後にインストーラーが正常に起動しない場合は、ダウンロードフォルダでファイルを見つけて手動で開いてください。',
|
||||
yesInstall: '今すぐインストール',
|
||||
noThanks: '後でインストール',
|
||||
fileLocation: 'ファイルの場所',
|
||||
@@ -172,7 +174,8 @@ export default {
|
||||
noTasks: 'インポートタスクがありません',
|
||||
clearTasks: 'タスクをクリア',
|
||||
clearTasksConfirmTitle: 'クリア確認',
|
||||
clearTasksConfirmContent: 'すべてのインポートタスク記録をクリアしますか?この操作は元に戻せません。',
|
||||
clearTasksConfirmContent:
|
||||
'すべてのインポートタスク記録をクリアしますか?この操作は元に戻せません。',
|
||||
confirm: '確認',
|
||||
cancel: 'キャンセル',
|
||||
clearTasksSuccess: 'タスクリストをクリアしました',
|
||||
@@ -187,4 +190,4 @@ export default {
|
||||
mv: 'MV',
|
||||
home: 'ホーム',
|
||||
search: '検索'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
description: 'あなたの寄付は開発・保守作業をサポートするために使用され、サーバー保守、ドメイン更新などが含まれます。',
|
||||
description:
|
||||
'あなたの寄付は開発・保守作業をサポートするために使用され、サーバー保守、ドメイン更新などが含まれます。',
|
||||
message: 'メッセージを残す際は、メールアドレスやGitHubユーザー名を記載してください。',
|
||||
refresh: 'リストを更新',
|
||||
toDonateList: 'コーヒーをおごる',
|
||||
noMessage: 'メッセージがありません',
|
||||
title: '寄付リスト'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -36,7 +36,8 @@ export default {
|
||||
},
|
||||
clear: {
|
||||
title: 'ダウンロード記録をクリア',
|
||||
message: 'すべてのダウンロード記録をクリアしますか?この操作はダウンロード済みの音楽ファイルを削除しませんが、すべての記録をクリアします。',
|
||||
message:
|
||||
'すべてのダウンロード記録をクリアしますか?この操作はダウンロード済みの音楽ファイルを削除しませんが、すべての記録をクリアします。',
|
||||
confirm: 'クリア確認',
|
||||
cancel: 'キャンセル',
|
||||
success: 'ダウンロード記録をクリアしました'
|
||||
@@ -84,4 +85,4 @@ export default {
|
||||
albumName: 'アルバム名'
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,4 +10,4 @@ export default {
|
||||
selectSongsFirst: 'まずダウンロードする楽曲を選択してください',
|
||||
descending: '降順',
|
||||
ascending: '昇順'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@ export default {
|
||||
title: '再生履歴',
|
||||
playCount: '{count}',
|
||||
getHistoryFailed: '履歴の取得に失敗しました'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -41,8 +41,10 @@ export default {
|
||||
uidLoginFailed: 'UIDログインに失敗しました。ユーザーIDが正しいか確認してください',
|
||||
autoGetCookieSuccess: 'Cookie自動取得成功',
|
||||
autoGetCookieFailed: 'Cookie自動取得失敗',
|
||||
autoGetCookieTip: 'NetEase Cloud Musicのログインページを開きます。ログイン完了後、ウィンドウを閉じてください'
|
||||
autoGetCookieTip:
|
||||
'NetEase Cloud Musicのログインページを開きます。ログイン完了後、ウィンドウを閉じてください'
|
||||
},
|
||||
qrTitle: 'NetEase Cloud Music QRコードログイン',
|
||||
uidWarning: '注意:UIDログインはユーザーの公開情報を表示するためのみ使用でき、ログイン権限が必要な機能にはアクセスできません。'
|
||||
};
|
||||
uidWarning:
|
||||
'注意:UIDログインはユーザーの公開情報を表示するためのみ使用でき、ログイン権限が必要な機能にはアクセスできません。'
|
||||
};
|
||||
|
||||
@@ -120,6 +120,7 @@ export default {
|
||||
cleared: 'プレイリストをクリアしました',
|
||||
empty: 'プレイリストが空です',
|
||||
clearConfirmTitle: 'プレイリストをクリア',
|
||||
clearConfirmContent: 'これによりプレイリスト内のすべての楽曲がクリアされ、現在の再生が停止されます。続行しますか?'
|
||||
clearConfirmContent:
|
||||
'これによりプレイリスト内のすべての楽曲がクリアされ、現在の再生が停止されます。続行しますか?'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,4 +24,4 @@ export default {
|
||||
mv: 'MV',
|
||||
bilibili: 'Bilibili'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -78,9 +78,11 @@ export default {
|
||||
autoPlay: '自動再生',
|
||||
autoPlayDesc: 'アプリを再起動した際に自動的に再生を継続するかどうか',
|
||||
showStatusBar: 'ステータスバーコントロール機能を表示するかどうか',
|
||||
showStatusBarContent: 'Macのステータスバーに音楽コントロール機能を表示できます(再起動後に有効)',
|
||||
showStatusBarContent:
|
||||
'Macのステータスバーに音楽コントロール機能を表示できます(再起動後に有効)',
|
||||
fallbackParser: '代替解析サービス (GD音楽台)',
|
||||
fallbackParserDesc: '「GD音楽台」にチェックが入っていて、通常の音源で再生できない場合、このサービスが使用されます。',
|
||||
fallbackParserDesc:
|
||||
'「GD音楽台」にチェックが入っていて、通常の音源で再生できない場合、このサービスが使用されます。',
|
||||
parserGD: 'GD 音楽台 (内蔵)',
|
||||
parserCustom: 'カスタム API',
|
||||
sourceLabels: {
|
||||
@@ -93,13 +95,14 @@ export default {
|
||||
},
|
||||
customApi: {
|
||||
sectionTitle: 'カスタム API 設定',
|
||||
enableHint: 'カスタム API を有効にするには、まずカスタム API をインポートする必要があります。',
|
||||
enableHint:
|
||||
'カスタム API を有効にするには、まずカスタム API をインポートする必要があります。',
|
||||
importConfig: 'JSON設定をインポート',
|
||||
currentSource: '現在の音源',
|
||||
notImported: 'カスタム音源はまだインポートされていません。',
|
||||
importSuccess: '音源のインポートに成功しました: {name}',
|
||||
importFailed: 'インポートに失敗しました: {message}',
|
||||
},
|
||||
importFailed: 'インポートに失敗しました: {message}'
|
||||
}
|
||||
},
|
||||
application: {
|
||||
closeAction: '閉じる動作',
|
||||
@@ -114,7 +117,8 @@ export default {
|
||||
download: 'ダウンロード管理',
|
||||
downloadDesc: 'ダウンロードリストボタンを常に表示するかどうか',
|
||||
unlimitedDownload: '無制限ダウンロード',
|
||||
unlimitedDownloadDesc: '有効にすると音楽を無制限でダウンロードします(ダウンロード失敗の可能性があります)。デフォルトは300曲制限',
|
||||
unlimitedDownloadDesc:
|
||||
'有効にすると音楽を無制限でダウンロードします(ダウンロード失敗の可能性があります)。デフォルトは300曲制限',
|
||||
downloadPath: 'ダウンロードディレクトリ',
|
||||
downloadPathDesc: '音楽ファイルのダウンロード場所を選択',
|
||||
remoteControl: 'リモートコントロール',
|
||||
@@ -130,7 +134,8 @@ export default {
|
||||
proxyPort: 'プロキシポート',
|
||||
proxyPortPlaceholder: 'プロキシポートを入力してください',
|
||||
realIP: 'realIP設定',
|
||||
realIPDesc: '制限により、このプロジェクトは海外での使用が制限されます。realIPパラメータを使用して国内IPを渡すことで解決できます',
|
||||
realIPDesc:
|
||||
'制限により、このプロジェクトは海外での使用が制限されます。realIPパラメータを使用して国内IPを渡すことで解決できます',
|
||||
messages: {
|
||||
proxySuccess: 'プロキシ設定を保存しました。アプリ再起動後に有効になります',
|
||||
proxyError: '入力が正しいかどうか確認してください',
|
||||
|
||||
@@ -25,4 +25,4 @@ export default {
|
||||
negativeText: 'キャンセル'
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,4 +45,4 @@ export default {
|
||||
deleteSuccess: '削除成功',
|
||||
deleteFailed: '削除失敗'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@ export default {
|
||||
hotSongs: '인기 곡',
|
||||
albums: '앨범',
|
||||
description: '아티스트 소개'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -53,4 +53,4 @@ export default {
|
||||
play: '재생',
|
||||
favorite: '즐겨찾기'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -41,7 +41,8 @@ export default {
|
||||
noDownloadUrl: '현재 시스템에 적합한 설치 패키지를 찾을 수 없습니다. 수동으로 다운로드해주세요',
|
||||
installConfirmTitle: '업데이트 설치',
|
||||
installConfirmContent: '앱을 닫고 업데이트를 설치하시겠습니까?',
|
||||
manualInstallTip: '앱을 닫은 후 설치 프로그램이 정상적으로 나타나지 않으면 다운로드 폴더에서 파일을 찾아 수동으로 열어주세요.',
|
||||
manualInstallTip:
|
||||
'앱을 닫은 후 설치 프로그램이 정상적으로 나타나지 않으면 다운로드 폴더에서 파일을 찾아 수동으로 열어주세요.',
|
||||
yesInstall: '지금 설치',
|
||||
noThanks: '나중에 설치',
|
||||
fileLocation: '파일 위치',
|
||||
@@ -172,7 +173,8 @@ export default {
|
||||
noTasks: '가져오기 작업이 없습니다',
|
||||
clearTasks: '작업 지우기',
|
||||
clearTasksConfirmTitle: '지우기 확인',
|
||||
clearTasksConfirmContent: '모든 가져오기 작업 기록을 지우시겠습니까? 이 작업은 되돌릴 수 없습니다.',
|
||||
clearTasksConfirmContent:
|
||||
'모든 가져오기 작업 기록을 지우시겠습니까? 이 작업은 되돌릴 수 없습니다.',
|
||||
confirm: '확인',
|
||||
cancel: '취소',
|
||||
clearTasksSuccess: '작업 목록이 지워졌습니다',
|
||||
@@ -187,4 +189,4 @@ export default {
|
||||
mv: 'MV',
|
||||
home: '홈',
|
||||
search: '검색'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
export default {
|
||||
description: '귀하의 기부는 서버 유지보수, 도메인 갱신 등을 포함한 개발 및 유지보수 작업을 지원하는 데 사용됩니다.',
|
||||
description:
|
||||
'귀하의 기부는 서버 유지보수, 도메인 갱신 등을 포함한 개발 및 유지보수 작업을 지원하는 데 사용됩니다.',
|
||||
message: '메시지를 남길 때 이메일이나 GitHub 이름을 남겨주세요.',
|
||||
refresh: '목록 새로고침',
|
||||
toDonateList: '커피 한 잔 사주세요',
|
||||
noMessage: '메시지가 없습니다',
|
||||
title: '기부 목록'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -36,7 +36,8 @@ export default {
|
||||
},
|
||||
clear: {
|
||||
title: '다운로드 기록 지우기',
|
||||
message: '모든 다운로드 기록을 지우시겠습니까? 이 작업은 다운로드된 음악 파일을 삭제하지 않지만 모든 기록을 지웁니다.',
|
||||
message:
|
||||
'모든 다운로드 기록을 지우시겠습니까? 이 작업은 다운로드된 음악 파일을 삭제하지 않지만 모든 기록을 지웁니다.',
|
||||
confirm: '지우기 확인',
|
||||
cancel: '취소',
|
||||
success: '다운로드 기록이 지워졌습니다'
|
||||
@@ -84,4 +85,4 @@ export default {
|
||||
albumName: '앨범명'
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,4 +10,4 @@ export default {
|
||||
selectSongsFirst: '먼저 다운로드할 곡을 선택해주세요',
|
||||
descending: '내림차순',
|
||||
ascending: '오름차순'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@ export default {
|
||||
title: '재생 기록',
|
||||
playCount: '{count}',
|
||||
getHistoryFailed: '기록 가져오기 실패'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -41,8 +41,10 @@ export default {
|
||||
uidLoginFailed: 'UID 로그인에 실패했습니다. 사용자 ID가 올바른지 확인하세요',
|
||||
autoGetCookieSuccess: 'Cookie 자동 가져오기 성공',
|
||||
autoGetCookieFailed: 'Cookie 자동 가져오기 실패',
|
||||
autoGetCookieTip: '넷이즈 클라우드 뮤직 로그인 페이지를 열겠습니다. 로그인 완료 후 창을 닫아주세요'
|
||||
autoGetCookieTip:
|
||||
'넷이즈 클라우드 뮤직 로그인 페이지를 열겠습니다. 로그인 완료 후 창을 닫아주세요'
|
||||
},
|
||||
qrTitle: '넷이즈 클라우드 뮤직 QR코드 로그인',
|
||||
uidWarning: '주의: UID 로그인은 사용자 공개 정보를 확인하는 데만 사용할 수 있으며, 로그인 권한이 필요한 기능에 액세스할 수 없습니다.'
|
||||
};
|
||||
uidWarning:
|
||||
'주의: UID 로그인은 사용자 공개 정보를 확인하는 데만 사용할 수 있으며, 로그인 권한이 필요한 기능에 액세스할 수 없습니다.'
|
||||
};
|
||||
|
||||
@@ -121,4 +121,4 @@ export default {
|
||||
clearConfirmTitle: '재생 목록 비우기',
|
||||
clearConfirmContent: '재생 목록의 모든 곡을 삭제하고 현재 재생을 중지합니다. 계속하시겠습니까?'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,4 +24,4 @@ export default {
|
||||
mv: 'MV',
|
||||
bilibili: 'B站'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -80,7 +80,8 @@ export default {
|
||||
showStatusBar: '상태바 제어 기능 표시 여부',
|
||||
showStatusBarContent: 'Mac 상태바에 음악 제어 기능을 표시할 수 있습니다 (재시작 후 적용)',
|
||||
fallbackParser: '대체 분석 서비스 (GD Music)',
|
||||
fallbackParserDesc: '"GD Music"을 선택하고 일반 음원을 사용할 수 없을 때 이 서비스를 사용합니다.',
|
||||
fallbackParserDesc:
|
||||
'"GD Music"을 선택하고 일반 음원을 사용할 수 없을 때 이 서비스를 사용합니다.',
|
||||
parserGD: 'GD Music (내장)',
|
||||
parserCustom: '사용자 지정 API',
|
||||
|
||||
@@ -101,8 +102,8 @@ export default {
|
||||
notImported: '아직 사용자 지정 음원을 가져오지 않았습니다.',
|
||||
importSuccess: '음원 가져오기 성공: {name}',
|
||||
importFailed: '가져오기 실패: {message}',
|
||||
enableHint: '사용하려면 먼저 JSON 구성 파일을 가져오세요',
|
||||
},
|
||||
enableHint: '사용하려면 먼저 JSON 구성 파일을 가져오세요'
|
||||
}
|
||||
},
|
||||
application: {
|
||||
closeAction: '닫기 동작',
|
||||
@@ -117,7 +118,8 @@ export default {
|
||||
download: '다운로드 관리',
|
||||
downloadDesc: '다운로드 목록 버튼을 항상 표시할지 여부',
|
||||
unlimitedDownload: '무제한 다운로드',
|
||||
unlimitedDownloadDesc: '활성화하면 음악을 무제한으로 다운로드합니다 (다운로드 실패가 발생할 수 있음), 기본 제한 300곡',
|
||||
unlimitedDownloadDesc:
|
||||
'활성화하면 음악을 무제한으로 다운로드합니다 (다운로드 실패가 발생할 수 있음), 기본 제한 300곡',
|
||||
downloadPath: '다운로드 디렉토리',
|
||||
downloadPathDesc: '음악 파일의 다운로드 위치 선택',
|
||||
remoteControl: '원격 제어',
|
||||
@@ -133,7 +135,8 @@ export default {
|
||||
proxyPort: '프록시 포트',
|
||||
proxyPortPlaceholder: '프록시 포트를 입력하세요',
|
||||
realIP: 'realIP 설정',
|
||||
realIPDesc: '제한으로 인해 이 프로젝트는 해외에서 사용할 때 제한을 받을 수 있으며, realIP 매개변수를 사용하여 국내 IP를 전달하여 해결할 수 있습니다',
|
||||
realIPDesc:
|
||||
'제한으로 인해 이 프로젝트는 해외에서 사용할 때 제한을 받을 수 있으며, realIP 매개변수를 사용하여 국내 IP를 전달하여 해결할 수 있습니다',
|
||||
messages: {
|
||||
proxySuccess: '프록시 설정이 저장되었습니다. 앱을 재시작한 후 적용됩니다',
|
||||
proxyError: '입력이 올바른지 확인하세요',
|
||||
|
||||
@@ -25,4 +25,4 @@ export default {
|
||||
negativeText: '취소'
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -45,4 +45,4 @@ export default {
|
||||
deleteSuccess: '삭제 성공',
|
||||
deleteFailed: '삭제 실패'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -81,7 +81,8 @@ export default {
|
||||
showStatusBarContent: '可以在您的mac状态栏显示音乐控制功能(重启后生效)',
|
||||
|
||||
fallbackParser: 'GD音乐台(music.gdstudio.xyz)设置',
|
||||
fallbackParserDesc: 'GD音乐台将自动尝试多个音乐平台进行解析,无需额外配置。优先级高于其他解析方式,但是请求可能较慢。感谢(music.gdstudio.xyz)\n',
|
||||
fallbackParserDesc:
|
||||
'GD音乐台将自动尝试多个音乐平台进行解析,无需额外配置。优先级高于其他解析方式,但是请求可能较慢。感谢(music.gdstudio.xyz)\n',
|
||||
parserGD: 'GD 音乐台 (内置)',
|
||||
parserCustom: '自定义 API',
|
||||
|
||||
@@ -103,8 +104,8 @@ export default {
|
||||
notImported: '尚未导入自定义音源。',
|
||||
importSuccess: '成功导入音源: {name}',
|
||||
importFailed: '导入失败: {message}',
|
||||
enableHint: '请先导入 JSON 配置文件才能启用',
|
||||
},
|
||||
enableHint: '请先导入 JSON 配置文件才能启用'
|
||||
}
|
||||
},
|
||||
application: {
|
||||
closeAction: '关闭行为',
|
||||
|
||||
@@ -101,8 +101,8 @@ export default {
|
||||
notImported: '尚未匯入自訂音源。',
|
||||
importSuccess: '成功匯入音源:{name}',
|
||||
importFailed: '匯入失敗:{message}',
|
||||
enableHint: '請先匯入 JSON 設定檔才能啟用',
|
||||
},
|
||||
enableHint: '請先匯入 JSON 設定檔才能啟用'
|
||||
}
|
||||
},
|
||||
application: {
|
||||
closeAction: '關閉行為',
|
||||
|
||||
Reference in New Issue
Block a user