- skin-site-api.ts 补 setDefault/clearDefault/defaultPlayer/switchMojang/adaptLegacyInternal,并恢复 deleteLauncherRelease - SkinSiteProfileView 增加玩家管理 UI 与状态 - en-US / zh-CN 各补 15 个 profile-view 文案
This commit is contained in:
1 parent
0aa901ad48
commit
bc37e5d436
4 files changed
+334
-26
No files matched your search
@@ -12,9 +12,16 @@ import {
|
||||
skinSiteUser,
|
||||
} from '@/composables/skin-site-session'
|
||||
import {
|
||||
skinSiteAddPlayer,
|
||||
skinSiteClearDefaultPlayer,
|
||||
skinSiteDefaultPlayer,
|
||||
skinSiteDeletePlayer,
|
||||
skinSiteDeleteTexture,
|
||||
type SkinSitePlayerSkin,
|
||||
skinSitePlayerSkin,
|
||||
type SkinSitePlayerSkin,
|
||||
skinSiteRenamePlayer,
|
||||
skinSiteSetDefaultPlayer,
|
||||
skinSiteSwitchMojang,
|
||||
skinSiteUploadTexture,
|
||||
type SkinTextureType,
|
||||
} from '@/helpers/skin-site-api'
|
||||
@@ -51,6 +58,36 @@ const messages = defineMessages({
|
||||
uploaded: { id: 'app.skin-site.profile-view.uploaded', defaultMessage: 'Texture updated.' },
|
||||
removed: { id: 'app.skin-site.profile-view.removed', defaultMessage: 'Texture removed.' },
|
||||
back: { id: 'app.skin-site.profile-view.back', defaultMessage: 'Back to home' },
|
||||
addPlayer: { id: 'app.skin-site.profile-view.add-player', defaultMessage: 'New player' },
|
||||
playerNamePlaceholder: {
|
||||
id: 'app.skin-site.profile-view.player-name-placeholder',
|
||||
defaultMessage: 'Player name',
|
||||
},
|
||||
confirm: { id: 'app.skin-site.profile-view.confirm', defaultMessage: 'Confirm' },
|
||||
cancel: { id: 'app.skin-site.profile-view.cancel', defaultMessage: 'Cancel' },
|
||||
rename: { id: 'app.skin-site.profile-view.rename', defaultMessage: 'Rename' },
|
||||
delete: { id: 'app.skin-site.profile-view.delete', defaultMessage: 'Delete' },
|
||||
setDefault: { id: 'app.skin-site.profile-view.set-default', defaultMessage: 'Set as default' },
|
||||
clearDefault: {
|
||||
id: 'app.skin-site.profile-view.clear-default',
|
||||
defaultMessage: 'Clear default',
|
||||
},
|
||||
toggleMojang: {
|
||||
id: 'app.skin-site.profile-view.toggle-mojang',
|
||||
defaultMessage: 'Toggle Mojang',
|
||||
},
|
||||
isDefault: { id: 'app.skin-site.profile-view.is-default', defaultMessage: 'Default' },
|
||||
added: { id: 'app.skin-site.profile-view.added', defaultMessage: 'Player added.' },
|
||||
renamed: { id: 'app.skin-site.profile-view.renamed', defaultMessage: 'Player renamed.' },
|
||||
deleted: { id: 'app.skin-site.profile-view.deleted', defaultMessage: 'Player deleted.' },
|
||||
defaultSet: {
|
||||
id: 'app.skin-site.profile-view.default-set',
|
||||
defaultMessage: 'Default player updated.',
|
||||
},
|
||||
mojangToggled: {
|
||||
id: 'app.skin-site.profile-view.mojang-toggled',
|
||||
defaultMessage: 'Mojang status updated.',
|
||||
},
|
||||
})
|
||||
const selectedId = ref<string | null>(null)
|
||||
const texture = ref<SkinSitePlayerSkin>({})
|
||||
@@ -93,6 +130,141 @@ watch(selectedId, (id) => {
|
||||
else texture.value = {}
|
||||
})
|
||||
|
||||
// --- Player management ---
|
||||
const defaultUuid = ref<string | null>(null)
|
||||
const busy = ref<string | null>(null)
|
||||
|
||||
async function loadDefaultPlayer() {
|
||||
if (!signedIn.value) {
|
||||
defaultUuid.value = null
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await skinSiteDefaultPlayer()
|
||||
defaultUuid.value = res.success ? (res.payload?.uuid ?? null) : null
|
||||
} catch {
|
||||
defaultUuid.value = null
|
||||
}
|
||||
}
|
||||
|
||||
const showAdd = ref(false)
|
||||
const newName = ref('')
|
||||
const renamingId = ref<string | null>(null)
|
||||
const renameValue = ref('')
|
||||
const confirmingDeleteId = ref<string | null>(null)
|
||||
|
||||
function resetDialogs() {
|
||||
showAdd.value = false
|
||||
newName.value = ''
|
||||
renamingId.value = null
|
||||
renameValue.value = ''
|
||||
confirmingDeleteId.value = null
|
||||
}
|
||||
|
||||
async function submitAdd() {
|
||||
const name = newName.value.trim()
|
||||
if (!name || busy.value) return
|
||||
busy.value = 'add'
|
||||
try {
|
||||
const res = await skinSiteAddPlayer(name)
|
||||
if (!res.success) throw new Error(res.errorMessage)
|
||||
addNotification({ type: 'success', title: formatMessage(messages.added) })
|
||||
resetDialogs()
|
||||
await requestSkinSitePlayers()
|
||||
await loadDefaultPlayer()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
busy.value = null
|
||||
}
|
||||
}
|
||||
|
||||
function startRename(player: { uuid: string; name: string }) {
|
||||
renamingId.value = player.uuid
|
||||
renameValue.value = player.name
|
||||
}
|
||||
|
||||
async function submitRename() {
|
||||
const name = renameValue.value.trim()
|
||||
if (!renamingId.value || !name || busy.value) return
|
||||
busy.value = 'rename'
|
||||
try {
|
||||
const res = await skinSiteRenamePlayer(renamingId.value, name)
|
||||
if (!res.success) throw new Error(res.errorMessage)
|
||||
addNotification({ type: 'success', title: formatMessage(messages.renamed) })
|
||||
resetDialogs()
|
||||
await requestSkinSitePlayers()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
busy.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function submitDelete(uuid: string) {
|
||||
if (busy.value) return
|
||||
busy.value = 'delete'
|
||||
try {
|
||||
const res = await skinSiteDeletePlayer(uuid)
|
||||
if (!res.success) throw new Error(res.errorMessage)
|
||||
addNotification({ type: 'success', title: formatMessage(messages.deleted) })
|
||||
resetDialogs()
|
||||
if (selectedId.value === uuid) selectedId.value = null
|
||||
await requestSkinSitePlayers()
|
||||
await loadDefaultPlayer()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
busy.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function setDefaultPlayer(uuid: string) {
|
||||
if (busy.value) return
|
||||
busy.value = 'default'
|
||||
try {
|
||||
const res = await skinSiteSetDefaultPlayer(uuid)
|
||||
if (!res.success) throw new Error(res.errorMessage)
|
||||
addNotification({ type: 'success', title: formatMessage(messages.defaultSet) })
|
||||
await loadDefaultPlayer()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
busy.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function clearDefaultPlayer() {
|
||||
if (busy.value) return
|
||||
busy.value = 'default'
|
||||
try {
|
||||
const res = await skinSiteClearDefaultPlayer()
|
||||
if (!res.success) throw new Error(res.errorMessage)
|
||||
addNotification({ type: 'success', title: formatMessage(messages.defaultSet) })
|
||||
await loadDefaultPlayer()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
busy.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleMojang(uuid: string) {
|
||||
if (busy.value) return
|
||||
busy.value = 'mojang'
|
||||
try {
|
||||
const res = await skinSiteSwitchMojang(uuid)
|
||||
if (!res.success) throw new Error(res.errorMessage)
|
||||
addNotification({ type: 'success', title: formatMessage(messages.mojangToggled) })
|
||||
await requestSkinSitePlayers()
|
||||
await loadDefaultPlayer()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
busy.value = null
|
||||
}
|
||||
}
|
||||
|
||||
async function onUpload(type: SkinTextureType, event: Event) {
|
||||
const input = event.target as HTMLInputElement
|
||||
const file = input.files?.[0]
|
||||
@@ -135,7 +307,10 @@ async function removeTexture(type: SkinTextureType) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (signedIn.value) void requestSkinSitePlayers().catch(() => {})
|
||||
if (signedIn.value) {
|
||||
void requestSkinSitePlayers().catch(() => {})
|
||||
void loadDefaultPlayer()
|
||||
}
|
||||
})
|
||||
|
||||
watch(signedIn, (value) => {
|
||||
@@ -161,9 +336,46 @@ watch(signedIn, (value) => {
|
||||
<div
|
||||
class="flex flex-col gap-2 rounded-2xl border border-solid border-surface-5 bg-bg-raised p-3"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<h3 class="m-0 text-base font-semibold text-contrast">
|
||||
{{ formatMessage(messages.title) }}
|
||||
</h3>
|
||||
<button
|
||||
v-if="!showAdd"
|
||||
type="button"
|
||||
class="shrink-0 rounded-full bg-brand px-2.5 py-1 text-xs font-semibold text-contrast hover:brightness-110"
|
||||
@click="showAdd = true"
|
||||
>
|
||||
+ {{ formatMessage(messages.addPlayer) }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="showAdd" class="flex flex-col gap-1.5 rounded-xl bg-button-bg p-2">
|
||||
<input
|
||||
v-model="newName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(messages.playerNamePlaceholder)"
|
||||
class="w-full rounded-lg border border-solid border-surface-5 bg-bg px-2 py-1 text-xs text-contrast outline-none focus:border-brand"
|
||||
@keyup.enter="submitAdd"
|
||||
/>
|
||||
<div class="flex gap-1.5">
|
||||
<button
|
||||
type="button"
|
||||
class="flex-1 rounded-lg bg-brand px-2 py-1 text-xs font-semibold text-contrast disabled:opacity-50"
|
||||
:disabled="busy === 'add' || !newName.trim()"
|
||||
@click="submitAdd"
|
||||
>
|
||||
{{ formatMessage(messages.confirm) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg bg-bg-raised px-2 py-1 text-xs font-semibold text-secondary"
|
||||
@click="resetDialogs"
|
||||
>
|
||||
{{ formatMessage(messages.cancel) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="playersLoading" class="flex items-center gap-2 text-sm text-secondary">
|
||||
<SpinnerIcon class="size-4 animate-spin" />
|
||||
@@ -172,18 +384,17 @@ watch(signedIn, (value) => {
|
||||
<p v-else-if="!players.length" class="m-0 text-sm text-secondary">
|
||||
{{ formatMessage(messages.noPlayers) }}
|
||||
</p>
|
||||
<button
|
||||
<div
|
||||
v-for="player in players"
|
||||
:key="player.uuid"
|
||||
type="button"
|
||||
class="flex items-center gap-2 rounded-xl px-2 py-1.5 text-left transition-colors"
|
||||
class="flex items-center gap-2 rounded-xl px-2 py-1.5 transition-colors"
|
||||
:class="
|
||||
player.uuid === selectedId
|
||||
? 'bg-brand-highlight text-contrast'
|
||||
: 'bg-button-bg hover:brightness-110'
|
||||
"
|
||||
@click="selectPlayer(player.uuid)"
|
||||
>
|
||||
>
|
||||
<Avatar
|
||||
:src="player.headDataUrl"
|
||||
:alt="player.name"
|
||||
@@ -195,7 +406,40 @@ watch(signedIn, (value) => {
|
||||
<span v-if="player.isMojang" class="shrink-0 text-[10px] uppercase text-secondary"
|
||||
>Mojang</span
|
||||
>
|
||||
<div class="flex shrink-0 items-center gap-1">
|
||||
<button
|
||||
v-if="defaultUuid === player.uuid"
|
||||
type="button"
|
||||
class="rounded px-1.5 py-0.5 text-[10px] font-semibold text-brand"
|
||||
@click.stop="clearDefaultPlayer"
|
||||
>
|
||||
{{ formatMessage(messages.clearDefault) }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="rounded px-1.5 py-0.5 text-[10px] font-semibold text-secondary hover:bg-bg"
|
||||
@click.stop="setDefaultPlayer(player.uuid)"
|
||||
>
|
||||
{{ formatMessage(messages.setDefault) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded px-1.5 py-0.5 text-[10px] font-semibold text-secondary hover:bg-bg"
|
||||
@click.stop="startRename(player)"
|
||||
>
|
||||
{{ formatMessage(messages.rename) }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded px-1.5 py-0.5 text-[10px] font-semibold text-red hover:bg-bg"
|
||||
:disabled="busy !== null"
|
||||
@click.stop="submitDelete(player.uuid)"
|
||||
>
|
||||
{{ formatMessage(messages.delete) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Preview + texture actions -->
|
||||
|
||||
@@ -336,6 +336,40 @@ export function skinSiteRenamePlayer(
|
||||
{ method: 'POST', type: 'skin' },
|
||||
)
|
||||
}
|
||||
|
||||
/** Mark a player as the account default (used by launcher login). */
|
||||
export function skinSiteSetDefaultPlayer(uuid: string): Promise<SkinSiteResponse<string>> {
|
||||
return skinSiteRequest<string>(`player/default/set?uuid=${encodeURIComponent(uuid)}`, {
|
||||
method: 'POST',
|
||||
type: 'skin',
|
||||
})
|
||||
}
|
||||
|
||||
/** Clear the account default player. */
|
||||
export function skinSiteClearDefaultPlayer(): Promise<SkinSiteResponse<string>> {
|
||||
return skinSiteRequest<string>('player/default', { method: 'DELETE', type: 'skin' })
|
||||
}
|
||||
|
||||
/** Fetch the account default player, if one is set. */
|
||||
export function skinSiteDefaultPlayer(): Promise<SkinSiteResponse<SkinSitePlayerInfo | null>> {
|
||||
return skinSiteRequest<SkinSitePlayerInfo | null>('player/default', { type: 'skin' })
|
||||
}
|
||||
|
||||
/** Toggle the Mojang (official) status of a player and resync its profile. */
|
||||
export function skinSiteSwitchMojang(uuid: string): Promise<SkinSiteResponse<string>> {
|
||||
return skinSiteRequest<string>(`player/${encodeURIComponent(uuid)}/switchMojang`, {
|
||||
method: 'GET',
|
||||
type: 'skin',
|
||||
})
|
||||
}
|
||||
|
||||
/** Convert a legacy internal player so it can log in through the modern flow. */
|
||||
export function skinSiteAdaptLegacyInternal(uuid: string): Promise<SkinSiteResponse<string>> {
|
||||
return skinSiteRequest<string>(`player/${encodeURIComponent(uuid)}/adaptLegacyInternal`, {
|
||||
method: 'POST',
|
||||
type: 'skin',
|
||||
})
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registration & password reset
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -414,8 +448,8 @@ export function skinSitePublicDonationSummary(): Promise<
|
||||
return skinSiteRequest<SkinSitePublicDonationSummary>('donation/summary', { auth: false })
|
||||
}
|
||||
|
||||
export function skinSiteDonationList(offset = 0): Promise<SkinSiteResponse<SkinSitePublicDonationPage>> {
|
||||
return skinSiteRequest<SkinSitePublicDonationPage>(`donation/list?limit=20&offset=${offset}`, {
|
||||
export function skinSiteDonationList(offset = 0): Promise<SkinSiteResponse<SkinSiteDonationPage>> {
|
||||
return skinSiteRequest<SkinSiteDonationPage>(`donation/list?limit=20&offset=${offset}`, {
|
||||
auth: false,
|
||||
})
|
||||
}
|
||||
@@ -1217,7 +1251,6 @@ export function skinSiteActivateLauncherRelease(
|
||||
export function skinSiteDeleteLauncherRelease(id: number): Promise<SkinSiteResponse<boolean>> {
|
||||
return skinSiteRequest<boolean>('launcher/admin/' + id, { method: 'DELETE' })
|
||||
}
|
||||
|
||||
export interface SkinSiteLauncherUploadStatus {
|
||||
id: string
|
||||
chunkSize: number
|
||||
@@ -1865,7 +1898,6 @@ export function skinSiteWikiUpdateSettings(
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export interface SkinSiteReviewPaperSummary {
|
||||
id: string
|
||||
enabled: boolean
|
||||
@@ -1908,9 +1940,7 @@ export interface SkinSiteReviewConfigData {
|
||||
prerequisitePermissions: string[]
|
||||
}
|
||||
|
||||
export function skinSiteReviewPaperList(): Promise<
|
||||
SkinSiteResponse<SkinSiteReviewPaperSummary[]>
|
||||
> {
|
||||
export function skinSiteReviewPaperList(): Promise<SkinSiteResponse<SkinSiteReviewPaperSummary[]>> {
|
||||
return skinSiteRequest<SkinSiteReviewPaperSummary[]>('review/admin/papers')
|
||||
}
|
||||
|
||||
@@ -1991,9 +2021,7 @@ export interface SkinSiteInviteCode {
|
||||
code: string
|
||||
}
|
||||
|
||||
export function skinSiteAdminBotInfo(
|
||||
userUuid: string,
|
||||
): Promise<SkinSiteResponse<SkinSiteBotInfo>> {
|
||||
export function skinSiteAdminBotInfo(userUuid: string): Promise<SkinSiteResponse<SkinSiteBotInfo>> {
|
||||
return skinSiteRequest<SkinSiteBotInfo>('admin/users/' + encodeURIComponent(userUuid) + '/bot')
|
||||
}
|
||||
|
||||
@@ -2047,7 +2075,9 @@ export function skinSiteAdminUserAudit(params?: {
|
||||
return skinSiteRequest<SkinSiteUserAdminAuditPage>('admin/users/audit' + suffix)
|
||||
}
|
||||
|
||||
export function skinSiteAdminInviteUser(email: string): Promise<SkinSiteResponse<SkinSiteInviteCode>> {
|
||||
export function skinSiteAdminInviteUser(
|
||||
email: string,
|
||||
): Promise<SkinSiteResponse<SkinSiteInviteCode>> {
|
||||
return skinSiteRequest<SkinSiteInviteCode>('admin/inviteCode', {
|
||||
method: 'POST',
|
||||
body: { email },
|
||||
@@ -2381,10 +2411,10 @@ export function skinSiteChatVoiceConfig(): Promise<
|
||||
export function skinSiteChatVoiceConfigUpdate(
|
||||
data: SkinSiteChatVoiceGlobalConfig,
|
||||
): Promise<SkinSiteResponse<SkinSiteChatVoiceGlobalConfigUpdateResult>> {
|
||||
return skinSiteRequest<SkinSiteChatVoiceGlobalConfigUpdateResult>(
|
||||
'chat/voice/admin/config',
|
||||
{ method: 'PUT', body: data },
|
||||
)
|
||||
return skinSiteRequest<SkinSiteChatVoiceGlobalConfigUpdateResult>('chat/voice/admin/config', {
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
})
|
||||
}
|
||||
|
||||
export function skinSiteChatVoiceLogs(
|
||||
@@ -2503,7 +2533,11 @@ export function skinSiteWikiMigrationCandidates(
|
||||
|
||||
export function skinSiteWikiMigrationDecide(
|
||||
candidateId: number,
|
||||
data: { decision: SkinSiteWikiMigrationDecision; targetTitle?: string | null; overwrite?: boolean },
|
||||
data: {
|
||||
decision: SkinSiteWikiMigrationDecision
|
||||
targetTitle?: string | null
|
||||
overwrite?: boolean
|
||||
},
|
||||
): Promise<SkinSiteResponse<void>> {
|
||||
return skinSiteRequest<void>('wiki/admin/migration/candidates/' + candidateId, {
|
||||
method: 'POST',
|
||||
@@ -2520,9 +2554,7 @@ export function skinSiteWikiMigrationPublish(
|
||||
)
|
||||
}
|
||||
|
||||
export function skinSiteWikiMigrationRollback(
|
||||
jobId: number,
|
||||
): Promise<SkinSiteResponse<void>> {
|
||||
export function skinSiteWikiMigrationRollback(jobId: number): Promise<SkinSiteResponse<void>> {
|
||||
return skinSiteRequest<void>('wiki/admin/migration/' + jobId + '/rollback', {
|
||||
method: 'POST',
|
||||
})
|
||||
@@ -2672,7 +2704,9 @@ export function skinSiteWikiPages(
|
||||
return skinSiteRequest<SkinSiteWikiPageList>('wiki/pages?' + query.toString())
|
||||
}
|
||||
|
||||
export function skinSiteWikiRecent(before?: number): Promise<SkinSiteResponse<SkinSiteWikiSearchPage>> {
|
||||
export function skinSiteWikiRecent(
|
||||
before?: number,
|
||||
): Promise<SkinSiteResponse<SkinSiteWikiSearchPage>> {
|
||||
const query = new URLSearchParams()
|
||||
if (before != null) query.set('before', String(before))
|
||||
return skinSiteRequest<SkinSiteWikiSearchPage>('wiki/recent?' + query.toString())
|
||||
|
||||
@@ -65,24 +65,39 @@
|
||||
"app.skin-site.map.open": { "message": "Open in browser" },
|
||||
"app.skin-site.map.server": { "message": "Server" },
|
||||
"app.skin-site.map.title": { "message": "Server map" },
|
||||
"app.skin-site.profile-view.add-player": { "message": "New player" },
|
||||
"app.skin-site.profile-view.added": { "message": "Player added." },
|
||||
"app.skin-site.profile-view.back": { "message": "Back to home" },
|
||||
"app.skin-site.profile-view.cancel": { "message": "Cancel" },
|
||||
"app.skin-site.profile-view.cape": { "message": "Cape" },
|
||||
"app.skin-site.profile-view.clear-default": { "message": "Clear default" },
|
||||
"app.skin-site.profile-view.confirm": { "message": "Confirm" },
|
||||
"app.skin-site.profile-view.default-set": { "message": "Default player updated." },
|
||||
"app.skin-site.profile-view.delete": { "message": "Delete" },
|
||||
"app.skin-site.profile-view.deleted": { "message": "Player deleted." },
|
||||
"app.skin-site.profile-view.elytra": { "message": "Elytra" },
|
||||
"app.skin-site.profile-view.is-default": { "message": "Default" },
|
||||
"app.skin-site.profile-view.loading": { "message": "Loading players…" },
|
||||
"app.skin-site.profile-view.mojang-toggled": { "message": "Mojang status updated." },
|
||||
"app.skin-site.profile-view.no-players": { "message": "No players yet." },
|
||||
"app.skin-site.profile-view.player-name-placeholder": { "message": "Player name" },
|
||||
"app.skin-site.profile-view.readonly": {
|
||||
"message": "Mojang accounts are managed by Mojang; textures cannot be edited here."
|
||||
},
|
||||
"app.skin-site.profile-view.remove": { "message": "Remove" },
|
||||
"app.skin-site.profile-view.removed": { "message": "Texture removed." },
|
||||
"app.skin-site.profile-view.rename": { "message": "Rename" },
|
||||
"app.skin-site.profile-view.renamed": { "message": "Player renamed." },
|
||||
"app.skin-site.profile-view.select-hint": {
|
||||
"message": "Select a player to preview and edit its textures."
|
||||
},
|
||||
"app.skin-site.profile-view.set-default": { "message": "Set as default" },
|
||||
"app.skin-site.profile-view.signed-out": {
|
||||
"message": "Sign in to manage your players."
|
||||
},
|
||||
"app.skin-site.profile-view.skin": { "message": "Skin" },
|
||||
"app.skin-site.profile-view.title": { "message": "Your players" },
|
||||
"app.skin-site.profile-view.toggle-mojang": { "message": "Toggle Mojang" },
|
||||
"app.skin-site.profile-view.upload": { "message": "Upload" },
|
||||
"app.skin-site.profile-view.uploaded": { "message": "Texture updated." },
|
||||
"app.skin-site.profile.avatar": { "message": "Avatar" },
|
||||
|
||||
@@ -61,24 +61,39 @@
|
||||
"app.skin-site.map.open": { "message": "在浏览器中打开" },
|
||||
"app.skin-site.map.server": { "message": "服务器" },
|
||||
"app.skin-site.map.title": { "message": "服务器地图" },
|
||||
"app.skin-site.profile-view.add-player": { "message": "新建角色" },
|
||||
"app.skin-site.profile-view.added": { "message": "角色已添加。" },
|
||||
"app.skin-site.profile-view.back": { "message": "返回主页" },
|
||||
"app.skin-site.profile-view.cancel": { "message": "取消" },
|
||||
"app.skin-site.profile-view.cape": { "message": "披风" },
|
||||
"app.skin-site.profile-view.clear-default": { "message": "取消默认" },
|
||||
"app.skin-site.profile-view.confirm": { "message": "确认" },
|
||||
"app.skin-site.profile-view.default-set": { "message": "默认角色已更新。" },
|
||||
"app.skin-site.profile-view.delete": { "message": "删除" },
|
||||
"app.skin-site.profile-view.deleted": { "message": "角色已删除。" },
|
||||
"app.skin-site.profile-view.elytra": { "message": "鞘翅" },
|
||||
"app.skin-site.profile-view.is-default": { "message": "默认" },
|
||||
"app.skin-site.profile-view.loading": { "message": "正在加载角色…" },
|
||||
"app.skin-site.profile-view.mojang-toggled": { "message": "正版状态已更新。" },
|
||||
"app.skin-site.profile-view.no-players": { "message": "暂无角色。" },
|
||||
"app.skin-site.profile-view.player-name-placeholder": { "message": "角色名" },
|
||||
"app.skin-site.profile-view.readonly": {
|
||||
"message": "Mojang 账号由 Mojang 管理,无法在此修改材质。"
|
||||
},
|
||||
"app.skin-site.profile-view.remove": { "message": "移除" },
|
||||
"app.skin-site.profile-view.removed": { "message": "材质已移除。" },
|
||||
"app.skin-site.profile-view.rename": { "message": "重命名" },
|
||||
"app.skin-site.profile-view.renamed": { "message": "角色已重命名。" },
|
||||
"app.skin-site.profile-view.select-hint": {
|
||||
"message": "选择角色以预览和修改其材质。"
|
||||
},
|
||||
"app.skin-site.profile-view.set-default": { "message": "设为默认" },
|
||||
"app.skin-site.profile-view.signed-out": {
|
||||
"message": "登录后管理你的角色。"
|
||||
},
|
||||
"app.skin-site.profile-view.skin": { "message": "皮肤" },
|
||||
"app.skin-site.profile-view.title": { "message": "我的角色" },
|
||||
"app.skin-site.profile-view.toggle-mojang": { "message": "切换正版" },
|
||||
"app.skin-site.profile-view.upload": { "message": "上传" },
|
||||
"app.skin-site.profile-view.uploaded": { "message": "材质已更新。" },
|
||||
"app.skin-site.profile.avatar": { "message": "头像" },
|
||||
|
||||
Reference in new issue
Block a user