You've already forked AstralRinth
forked from didirus/AstralRinth
Versions environments updates (#4949)
* add environment to version page metadata card * remove environment migration warnings * show settings/environments in nav only for staff * use v2 versions route due to regressions * add modpack incorrect loaders migration * remove modpack migration step * remove unused var * run pnpm intl:extract * componentize environment migration page * rename environment selector * rename environment selector pt2 * add migration modal to admonition * hide environments in settings and show message * show environment in project versions table * pnpm fix * pnpm fix on ui package * intl:extract * fix: .value * lower case file * add icon to environment tags and use i18n * Update apps/frontend/src/pages/[type]/[id].vue Co-authored-by: Calum H. <contact@cal.engineer> Signed-off-by: Truman Gao <106889354+tdgao@users.noreply.github.com> * open migration modal from warning icon in project dashboard * fix settings side nav icon * use useRoute composable * pnpm fix * intl:extract * fix import * fix import again * run pnpm prepr * fix designMessage import * fix environment fetch * fix environment fetch properly without key conflict * fix environment refetching * fix not using current versions in table to check different environments * fix download tooltip --------- Signed-off-by: Truman Gao <106889354+tdgao@users.noreply.github.com> Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
This commit is contained in:
@@ -42,7 +42,12 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="versions.length > 0"
|
||||
class="flex flex-col gap-4 rounded-2xl bg-bg-raised px-6 pb-8 pt-4 supports-[grid-template-columns:subgrid]:grid supports-[grid-template-columns:subgrid]:grid-cols-[1fr_min-content] sm:px-8 supports-[grid-template-columns:subgrid]:sm:grid-cols-[min-content_auto_auto_auto_min-content] supports-[grid-template-columns:subgrid]:xl:grid-cols-[min-content_auto_auto_auto_auto_auto_min-content]"
|
||||
class="flex flex-col gap-4 rounded-2xl bg-bg-raised px-6 pb-8 pt-4 supports-[grid-template-columns:subgrid]:grid supports-[grid-template-columns:subgrid]:grid-cols-[1fr_min-content] sm:px-8 supports-[grid-template-columns:subgrid]:sm:grid-cols-[min-content_auto_auto_auto_min-content]"
|
||||
:class="[
|
||||
hasMultipleEnvironments
|
||||
? 'supports-[grid-template-columns:subgrid]:xl:grid-cols-[min-content_auto_auto_auto_auto_auto_auto_min-content] has-environment'
|
||||
: 'supports-[grid-template-columns:subgrid]:xl:grid-cols-[min-content_auto_auto_auto_auto_auto_min-content] no-environment',
|
||||
]"
|
||||
>
|
||||
<div class="versions-grid-row">
|
||||
<div class="w-9 max-sm:hidden"></div>
|
||||
@@ -57,6 +62,12 @@
|
||||
>
|
||||
Platforms
|
||||
</div>
|
||||
<div
|
||||
v-if="hasMultipleEnvironments"
|
||||
class="text-sm font-bold text-contrast max-sm:hidden sm:max-xl:collapse sm:max-xl:hidden"
|
||||
>
|
||||
Environment
|
||||
</div>
|
||||
<div
|
||||
class="text-sm font-bold text-contrast max-sm:hidden sm:max-xl:collapse sm:max-xl:hidden"
|
||||
>
|
||||
@@ -144,6 +155,24 @@
|
||||
</TagItem>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="hasMultipleEnvironments"
|
||||
v-tooltip="
|
||||
ENVIRONMENTS_COPY[version.environment || 'unknown']?.description
|
||||
? formatMessage(ENVIRONMENTS_COPY[version.environment || 'unknown'].description)
|
||||
: undefined
|
||||
"
|
||||
class="flex items-center"
|
||||
>
|
||||
<TagItem class="z-[1] text-center">
|
||||
<component :is="ENVIRONMENTS_COPY[version.environment || 'unknown']?.icon" />
|
||||
{{
|
||||
ENVIRONMENTS_COPY[version.environment || 'unknown']?.title
|
||||
? formatMessage(ENVIRONMENTS_COPY[version.environment || 'unknown'].title)
|
||||
: ''
|
||||
}}
|
||||
</TagItem>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col justify-center gap-1 max-sm:flex-row max-sm:justify-start max-sm:gap-3 xl:contents"
|
||||
@@ -215,12 +244,14 @@ import { commonMessages } from '../../utils/common-messages'
|
||||
import AutoLink from '../base/AutoLink.vue'
|
||||
import TagItem from '../base/TagItem.vue'
|
||||
import { Pagination, VersionChannelIndicator, VersionFilterControl } from '../index'
|
||||
import { ENVIRONMENTS_COPY } from './settings/environment/environments'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const formatRelativeTime = useRelativeTime()
|
||||
|
||||
type VersionWithDisplayUrlEnding = Version & {
|
||||
displayUrlEnding: string
|
||||
environment?: Labrinth.Projects.v3.Environment
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -260,6 +291,11 @@ const selectedPlatforms: Ref<string[]> = computed(
|
||||
)
|
||||
const selectedChannels: Ref<string[]> = computed(() => versionFilters.value?.selectedChannels ?? [])
|
||||
|
||||
const hasMultipleEnvironments = computed(() => {
|
||||
const environments = new Set(currentVersions.value.map((v) => v.environment).filter(Boolean))
|
||||
return environments.size > 1
|
||||
})
|
||||
|
||||
const filteredVersions = computed(() => {
|
||||
return props.versions.filter(
|
||||
(version) =>
|
||||
@@ -321,6 +357,14 @@ function updateQuery(newQueries: Record<string, string | string[] | undefined |
|
||||
</script>
|
||||
<style scoped>
|
||||
.versions-grid-row {
|
||||
@apply grid grid-cols-[1fr_min-content] gap-4 supports-[grid-template-columns:subgrid]:col-span-full supports-[grid-template-columns:subgrid]:!grid-cols-subgrid sm:grid-cols-[min-content_1fr_1fr_1fr_min-content] xl:grid-cols-[min-content_1fr_1fr_1fr_1fr_1fr_min-content];
|
||||
@apply grid grid-cols-[1fr_min-content] gap-4 supports-[grid-template-columns:subgrid]:col-span-full supports-[grid-template-columns:subgrid]:!grid-cols-subgrid sm:grid-cols-[min-content_1fr_1fr_1fr_min-content];
|
||||
}
|
||||
|
||||
.has-environment .versions-grid-row {
|
||||
@apply xl:grid-cols-[min-content_1fr_1fr_1fr_1fr_1fr_1fr_min-content];
|
||||
}
|
||||
|
||||
.no-environment .versions-grid-row {
|
||||
@apply xl:grid-cols-[min-content_1fr_1fr_1fr_1fr_1fr_min-content];
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
:action="() => router.push(`/${project.project_type}s?g=categories:${platform}`)"
|
||||
:style="`--_color: var(--color-platform-${platform})`"
|
||||
>
|
||||
<svg v-html="tags.loaders.find((x) => x.name === platform).icon"></svg>
|
||||
<svg v-html="tags.loaders.find((x) => x.name === platform)?.icon"></svg>
|
||||
{{ formatCategory(platform) }}
|
||||
</TagItem>
|
||||
</div>
|
||||
@@ -69,6 +69,7 @@
|
||||
</TagItem>
|
||||
<TagItem
|
||||
v-if="
|
||||
// @ts-ignore
|
||||
project.project_type !== 'datapack' &&
|
||||
project.client_side !== 'unsupported' &&
|
||||
project.server_side !== 'unsupported' &&
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
<script setup lang="ts">
|
||||
import { CheckIcon } from '@modrinth/assets'
|
||||
import {
|
||||
Admonition,
|
||||
commonProjectSettingsMessages,
|
||||
defineMessages,
|
||||
EnvironmentSelector,
|
||||
injectModrinthClient,
|
||||
injectNotificationManager,
|
||||
injectProjectPageContext,
|
||||
UnsavedChangesPopup,
|
||||
useSavable,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const { currentMember, projectV2, projectV3, refreshProject } = injectProjectPageContext()
|
||||
const { handleError } = injectNotificationManager()
|
||||
const client = injectModrinthClient()
|
||||
|
||||
const saving = ref(false)
|
||||
|
||||
const supportsEnvironment = computed(() =>
|
||||
projectV3.value.project_types.some((type) => ['mod', 'modpack'].includes(type)),
|
||||
)
|
||||
|
||||
const needsToVerify = computed(
|
||||
() =>
|
||||
projectV3.value.side_types_migration_review_status === 'pending' &&
|
||||
(projectV3.value.environment?.length ?? 0) > 0 &&
|
||||
projectV3.value.environment?.[0] !== 'unknown' &&
|
||||
supportsEnvironment.value,
|
||||
)
|
||||
|
||||
const hasPermission = computed(() => {
|
||||
const EDIT_DETAILS = 1 << 2
|
||||
return (currentMember.value?.permissions & EDIT_DETAILS) === EDIT_DETAILS
|
||||
})
|
||||
|
||||
function getInitialEnv() {
|
||||
return projectV3.value.environment?.length === 1 ? projectV3.value.environment[0] : undefined
|
||||
}
|
||||
|
||||
const { saved, current, reset, save } = useSavable(
|
||||
() => ({
|
||||
environment: getInitialEnv(),
|
||||
side_types_migration_review_status: projectV3.value.side_types_migration_review_status,
|
||||
}),
|
||||
({ environment, side_types_migration_review_status }) => {
|
||||
saving.value = true
|
||||
side_types_migration_review_status = 'reviewed'
|
||||
client.labrinth.projects_v3
|
||||
.edit(projectV2.value.id, { environment, side_types_migration_review_status })
|
||||
.then(() => refreshProject().then(reset))
|
||||
.catch(handleError)
|
||||
.finally(() => (saving.value = false))
|
||||
},
|
||||
)
|
||||
// Set current to reviewed, which will trigger unsaved changes popup.
|
||||
// It should not be possible to save without reviewing it.
|
||||
const originalEnv = getInitialEnv()
|
||||
if (originalEnv && originalEnv !== 'unknown') {
|
||||
current.value.side_types_migration_review_status = 'reviewed'
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
verifyButton: {
|
||||
id: 'project.settings.environment.verification.verify-button',
|
||||
defaultMessage: 'Verify',
|
||||
},
|
||||
verifyLabel: {
|
||||
id: 'project.settings.environment.verification.verify-text',
|
||||
defaultMessage: `Verify that this project's environment is set correctly.`,
|
||||
},
|
||||
wrongProjectTypeTitle: {
|
||||
id: 'project.settings.environment.notice.wrong-project-type.title',
|
||||
defaultMessage: `This project type does not support environment metadata`,
|
||||
},
|
||||
wrongProjectTypeDescription: {
|
||||
id: 'project.settings.environment.notice.wrong-project-type.description',
|
||||
defaultMessage: `Only mod or modpack projects can have environment metadata.`,
|
||||
},
|
||||
missingEnvTitle: {
|
||||
id: 'project.settings.environment.notice.missing-env.title',
|
||||
defaultMessage: `Please select an environment for your project`,
|
||||
},
|
||||
missingEnvDescription: {
|
||||
id: 'project.settings.environment.notice.missing-env.description',
|
||||
defaultMessage: `Your project is missing environment metadata, please select the appropriate option below.`,
|
||||
},
|
||||
multipleEnvironmentsTitle: {
|
||||
id: 'project.settings.environment.notice.multiple-environments.title',
|
||||
defaultMessage: 'Your project has multiple environments',
|
||||
},
|
||||
multipleEnvironmentsDescription: {
|
||||
id: 'project.settings.environment.notice.multiple-environments.description',
|
||||
defaultMessage:
|
||||
"Different versions of your project have different environments selected, so you can't edit them globally at this time.",
|
||||
},
|
||||
reviewOptionsTitle: {
|
||||
id: 'project.settings.environment.notice.review-options.title',
|
||||
defaultMessage: 'Please review the options below',
|
||||
},
|
||||
reviewOptionsDescription: {
|
||||
id: 'project.settings.environment.notice.review-options.description',
|
||||
defaultMessage:
|
||||
"We've just overhauled the Environments system on Modrinth and new options are now available. Please ensure the correct option is selected below and then click 'Verify' when you're done!",
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<Admonition
|
||||
v-if="!supportsEnvironment"
|
||||
type="critical"
|
||||
:header="formatMessage(messages.wrongProjectTypeTitle)"
|
||||
:body="formatMessage(messages.wrongProjectTypeDescription)"
|
||||
class="mb-3"
|
||||
/>
|
||||
<template v-else>
|
||||
<Admonition
|
||||
v-if="!hasPermission"
|
||||
type="critical"
|
||||
:header="formatMessage(commonProjectSettingsMessages.noPermissionTitle)"
|
||||
:body="formatMessage(commonProjectSettingsMessages.noPermissionDescription)"
|
||||
class="mb-3"
|
||||
/>
|
||||
<Admonition
|
||||
v-else-if="
|
||||
!projectV3.environment ||
|
||||
projectV3.environment.length === 0 ||
|
||||
(projectV3.environment.length === 1 && projectV3.environment[0] === 'unknown')
|
||||
"
|
||||
type="critical"
|
||||
:header="formatMessage(messages.missingEnvTitle)"
|
||||
:body="formatMessage(messages.missingEnvDescription)"
|
||||
class="mb-3"
|
||||
/>
|
||||
<Admonition
|
||||
v-else-if="projectV3.environment.length > 1"
|
||||
type="info"
|
||||
:header="formatMessage(messages.multipleEnvironmentsTitle)"
|
||||
:body="formatMessage(messages.multipleEnvironmentsDescription)"
|
||||
class="mb-3"
|
||||
/>
|
||||
<Admonition
|
||||
v-else-if="needsToVerify"
|
||||
type="warning"
|
||||
:header="formatMessage(messages.reviewOptionsTitle)"
|
||||
:body="formatMessage(messages.reviewOptionsDescription)"
|
||||
class="mb-3"
|
||||
/>
|
||||
<EnvironmentSelector
|
||||
v-model="current.environment"
|
||||
:disabled="!hasPermission || (projectV3?.environment?.length ?? 0) > 1"
|
||||
/>
|
||||
</template>
|
||||
<UnsavedChangesPopup
|
||||
v-if="supportsEnvironment && hasPermission && (projectV3?.environment?.length ?? 0) <= 1"
|
||||
:original="saved"
|
||||
:modified="current"
|
||||
:saving="saving"
|
||||
:can-reset="!needsToVerify"
|
||||
:text="needsToVerify ? messages.verifyLabel : undefined"
|
||||
:save-label="needsToVerify ? messages.verifyButton : undefined"
|
||||
:save-icon="needsToVerify ? CheckIcon : undefined"
|
||||
@reset="reset"
|
||||
@save="save"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -33,7 +33,10 @@ const optionLabelFormat = defineMessage({
|
||||
defaultMessage: '{title}: {description}',
|
||||
})
|
||||
|
||||
const OUTER_OPTIONS = {
|
||||
const OUTER_OPTIONS: Record<
|
||||
string,
|
||||
EnvironmentRadioOption & { suboptions: Record<string, EnvironmentRadioOption> }
|
||||
> = {
|
||||
client: {
|
||||
title: defineMessage({
|
||||
id: 'project.settings.environment.client_only.title',
|
||||
@@ -125,10 +128,8 @@ const OUTER_OPTIONS = {
|
||||
}),
|
||||
suboptions: {},
|
||||
},
|
||||
} as const satisfies Record<
|
||||
string,
|
||||
EnvironmentRadioOption & { suboptions: Record<string, EnvironmentRadioOption> }
|
||||
>
|
||||
} as const
|
||||
|
||||
type OuterOptionKey = keyof typeof OUTER_OPTIONS
|
||||
type SubOptionKey = ValidKeys<(typeof OUTER_OPTIONS)[keyof typeof OUTER_OPTIONS]['suboptions']>
|
||||
|
||||
@@ -248,7 +249,7 @@ const simulateSave = ref(false)
|
||||
:aria-label="
|
||||
formatMessage(optionLabelFormat, {
|
||||
title: formatMessage(title),
|
||||
description: formatMessage(description),
|
||||
description: description ? formatMessage(description) : '',
|
||||
})
|
||||
"
|
||||
@select="
|
||||
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<NewModal ref="modal" :scrollable="true" max-content-height="82vh" :closable="true">
|
||||
<template #title>
|
||||
<span class="text-lg font-extrabold text-contrast">Edit project Environment</span>
|
||||
</template>
|
||||
<div class="mb-24 max-w-[600px]">
|
||||
<EnvironmentMigration />
|
||||
</div>
|
||||
</NewModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, useTemplateRef } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { NewModal } from '../../../modal'
|
||||
import EnvironmentMigration from './EnvironmentMigration.vue'
|
||||
|
||||
const modal = useTemplateRef<InstanceType<typeof NewModal>>('modal')
|
||||
|
||||
function show() {
|
||||
modal.value?.show()
|
||||
}
|
||||
|
||||
function hide() {
|
||||
modal.value?.hide()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const route = useRoute()
|
||||
if (route.query.showEnvironmentMigrationWarning === 'true') {
|
||||
show()
|
||||
}
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
show,
|
||||
hide,
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,129 @@
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { ClientIcon, MonitorSmartphoneIcon, ServerIcon, UserIcon } from '@modrinth/assets'
|
||||
import type { Component } from 'vue'
|
||||
|
||||
import { defineMessage, type MessageDescriptor } from '../../../../composables/i18n'
|
||||
|
||||
export const ENVIRONMENTS_COPY: Record<
|
||||
Labrinth.Projects.v3.Environment,
|
||||
{ title: MessageDescriptor; description: MessageDescriptor; icon?: Component }
|
||||
> = {
|
||||
client_only: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.client-only.title',
|
||||
defaultMessage: 'Client-side only',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.client-only.description',
|
||||
defaultMessage:
|
||||
'All functionality is done client-side and is compatible with vanilla servers.',
|
||||
}),
|
||||
icon: ClientIcon,
|
||||
},
|
||||
server_only: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.server-only.title',
|
||||
defaultMessage: 'Server-side only',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.server-only.description',
|
||||
defaultMessage:
|
||||
'All functionality is done server-side and is compatible with vanilla clients.',
|
||||
}),
|
||||
icon: ServerIcon,
|
||||
},
|
||||
singleplayer_only: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.singleplayer-only.title',
|
||||
defaultMessage: 'Singleplayer only',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.singleplayer-only.description',
|
||||
defaultMessage:
|
||||
'Only functions in Singleplayer or when not connected to a Multiplayer server.',
|
||||
}),
|
||||
icon: UserIcon,
|
||||
},
|
||||
dedicated_server_only: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.dedicated-server-only.title',
|
||||
defaultMessage: 'Server-side only',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.dedicated-server-only.description',
|
||||
defaultMessage:
|
||||
'All functionality is done server-side and is compatible with vanilla clients.',
|
||||
}),
|
||||
icon: ServerIcon,
|
||||
},
|
||||
client_and_server: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.client-and-server.title',
|
||||
defaultMessage: 'Client and server',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.client-and-server.description',
|
||||
defaultMessage:
|
||||
'Has some functionality on both the client and server, even if only partially.',
|
||||
}),
|
||||
icon: MonitorSmartphoneIcon,
|
||||
},
|
||||
client_only_server_optional: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.client-only-server-optional.title',
|
||||
defaultMessage: 'Client and server',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.client-only-server-optional.description',
|
||||
defaultMessage:
|
||||
'Has some functionality on both the client and server, even if only partially.',
|
||||
}),
|
||||
icon: MonitorSmartphoneIcon,
|
||||
},
|
||||
server_only_client_optional: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.server-only-client-optional.title',
|
||||
defaultMessage: 'Client and server',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.server-only-client-optional.description',
|
||||
defaultMessage:
|
||||
'Has some functionality on both the client and server, even if only partially.',
|
||||
}),
|
||||
icon: MonitorSmartphoneIcon,
|
||||
},
|
||||
client_or_server: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.client-or-server.title',
|
||||
defaultMessage: 'Client and server',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.client-or-server.description',
|
||||
defaultMessage:
|
||||
'Has some functionality on both the client and server, even if only partially.',
|
||||
}),
|
||||
icon: MonitorSmartphoneIcon,
|
||||
},
|
||||
client_or_server_prefers_both: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.client-or-server-prefers-both.title',
|
||||
defaultMessage: 'Client and server',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.client-or-server-prefers-both.description',
|
||||
defaultMessage:
|
||||
'Has some functionality on both the client and server, even if only partially.',
|
||||
}),
|
||||
icon: MonitorSmartphoneIcon,
|
||||
},
|
||||
unknown: {
|
||||
title: defineMessage({
|
||||
id: 'project.environment.unknown.title',
|
||||
defaultMessage: 'Unknown environment',
|
||||
}),
|
||||
description: defineMessage({
|
||||
id: 'project.environment.unknown.description',
|
||||
defaultMessage: 'The environment for this version could not be determined.',
|
||||
}),
|
||||
},
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
// Environment
|
||||
export { default as ProjectSettingsEnvSelector } from './environment/ProjectSettingsEnvSelector.vue'
|
||||
export { default as EnvironmentMigration } from './environment/EnvironmentMigration.vue'
|
||||
export { ENVIRONMENTS_COPY } from './environment/environments'
|
||||
export { default as EnvironmentSelector } from './environment/EnvironmentSelector.vue'
|
||||
export { default as ProjectEnvironmentModal } from './environment/ProjectEnvironmentModal.vue'
|
||||
|
||||
@@ -677,6 +677,66 @@
|
||||
"project.about.links.wiki": {
|
||||
"defaultMessage": "Visit wiki"
|
||||
},
|
||||
"project.environment.client-and-server.description": {
|
||||
"defaultMessage": "Has some functionality on both the client and server, even if only partially."
|
||||
},
|
||||
"project.environment.client-and-server.title": {
|
||||
"defaultMessage": "Client and server"
|
||||
},
|
||||
"project.environment.client-only-server-optional.description": {
|
||||
"defaultMessage": "Has some functionality on both the client and server, even if only partially."
|
||||
},
|
||||
"project.environment.client-only-server-optional.title": {
|
||||
"defaultMessage": "Client and server"
|
||||
},
|
||||
"project.environment.client-only.description": {
|
||||
"defaultMessage": "All functionality is done client-side and is compatible with vanilla servers."
|
||||
},
|
||||
"project.environment.client-only.title": {
|
||||
"defaultMessage": "Client-side only"
|
||||
},
|
||||
"project.environment.client-or-server-prefers-both.description": {
|
||||
"defaultMessage": "Has some functionality on both the client and server, even if only partially."
|
||||
},
|
||||
"project.environment.client-or-server-prefers-both.title": {
|
||||
"defaultMessage": "Client and server"
|
||||
},
|
||||
"project.environment.client-or-server.description": {
|
||||
"defaultMessage": "Has some functionality on both the client and server, even if only partially."
|
||||
},
|
||||
"project.environment.client-or-server.title": {
|
||||
"defaultMessage": "Client and server"
|
||||
},
|
||||
"project.environment.dedicated-server-only.description": {
|
||||
"defaultMessage": "All functionality is done server-side and is compatible with vanilla clients."
|
||||
},
|
||||
"project.environment.dedicated-server-only.title": {
|
||||
"defaultMessage": "Server-side only"
|
||||
},
|
||||
"project.environment.server-only-client-optional.description": {
|
||||
"defaultMessage": "Has some functionality on both the client and server, even if only partially."
|
||||
},
|
||||
"project.environment.server-only-client-optional.title": {
|
||||
"defaultMessage": "Client and server"
|
||||
},
|
||||
"project.environment.server-only.description": {
|
||||
"defaultMessage": "All functionality is done server-side and is compatible with vanilla clients."
|
||||
},
|
||||
"project.environment.server-only.title": {
|
||||
"defaultMessage": "Server-side only"
|
||||
},
|
||||
"project.environment.singleplayer-only.description": {
|
||||
"defaultMessage": "Only functions in Singleplayer or when not connected to a Multiplayer server."
|
||||
},
|
||||
"project.environment.singleplayer-only.title": {
|
||||
"defaultMessage": "Singleplayer only"
|
||||
},
|
||||
"project.environment.unknown.description": {
|
||||
"defaultMessage": "The environment for this version could not be determined."
|
||||
},
|
||||
"project.environment.unknown.title": {
|
||||
"defaultMessage": "Unknown environment"
|
||||
},
|
||||
"project.settings.analytics.title": {
|
||||
"defaultMessage": "Analytics"
|
||||
},
|
||||
@@ -710,6 +770,30 @@
|
||||
"project.settings.environment.client_only.title": {
|
||||
"defaultMessage": "Client-side only"
|
||||
},
|
||||
"project.settings.environment.notice.missing-env.description": {
|
||||
"defaultMessage": "Your project is missing environment metadata, please select the appropriate option below."
|
||||
},
|
||||
"project.settings.environment.notice.missing-env.title": {
|
||||
"defaultMessage": "Please select an environment for your project"
|
||||
},
|
||||
"project.settings.environment.notice.multiple-environments.description": {
|
||||
"defaultMessage": "Different versions of your project have different environments selected, so you can't edit them globally at this time."
|
||||
},
|
||||
"project.settings.environment.notice.multiple-environments.title": {
|
||||
"defaultMessage": "Your project has multiple environments"
|
||||
},
|
||||
"project.settings.environment.notice.review-options.description": {
|
||||
"defaultMessage": "We've just overhauled the Environments system on Modrinth and new options are now available. Please ensure the correct option is selected below and then click 'Verify' when you're done!"
|
||||
},
|
||||
"project.settings.environment.notice.review-options.title": {
|
||||
"defaultMessage": "Please review the options below"
|
||||
},
|
||||
"project.settings.environment.notice.wrong-project-type.description": {
|
||||
"defaultMessage": "Only mod or modpack projects can have environment metadata."
|
||||
},
|
||||
"project.settings.environment.notice.wrong-project-type.title": {
|
||||
"defaultMessage": "This project type does not support environment metadata"
|
||||
},
|
||||
"project.settings.environment.server_only.dedicated_only.title": {
|
||||
"defaultMessage": "Dedicated server only"
|
||||
},
|
||||
@@ -737,6 +821,12 @@
|
||||
"project.settings.environment.title": {
|
||||
"defaultMessage": "Environment"
|
||||
},
|
||||
"project.settings.environment.verification.verify-button": {
|
||||
"defaultMessage": "Verify"
|
||||
},
|
||||
"project.settings.environment.verification.verify-text": {
|
||||
"defaultMessage": "Verify that this project's environment is set correctly."
|
||||
},
|
||||
"project.settings.gallery.title": {
|
||||
"defaultMessage": "Gallery"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user