Sort filters and add translations for servers (#5493)
* Translate and sort server filters * Set team_members to unknown[] * Additional fixes after merge * Additional translations * Replace "IP" with "server address" * Prioritize English and user language
This commit is contained in:
@@ -91,7 +91,7 @@
|
||||
<ButtonStyled class="flex-1">
|
||||
<button @click="hide">
|
||||
<XIcon />
|
||||
{{ formatMessage(messages.close) }}
|
||||
{{ formatMessage(commonMessages.closeButton) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="green" class="flex-1">
|
||||
@@ -108,6 +108,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CheckIcon, DownloadIcon, XIcon } from '@modrinth/assets'
|
||||
import { commonMessages } from '@modrinth/ui'
|
||||
import { computed, nextTick, onUnmounted, ref } from 'vue'
|
||||
|
||||
import { defineMessages, useVIntl } from '../../composables/i18n'
|
||||
@@ -142,10 +143,6 @@ const messages = defineMessages({
|
||||
id: 'modal.open-in-app.opening-automatically',
|
||||
defaultMessage: 'The Modrinth App will open automatically...',
|
||||
},
|
||||
close: {
|
||||
id: 'modal.open-in-app.close',
|
||||
defaultMessage: 'Close',
|
||||
},
|
||||
getApp: {
|
||||
id: 'modal.open-in-app.get-app',
|
||||
defaultMessage: 'Get Modrinth App',
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{{ organization.name }}
|
||||
</span>
|
||||
<span class="text-secondary text-sm font-medium flex items-center gap-1"
|
||||
><OrganizationIcon /> Organization</span
|
||||
><OrganizationIcon /> {{ formatMessage(messages.organization) }}</span
|
||||
>
|
||||
</div>
|
||||
</AutoLink>
|
||||
@@ -117,5 +117,9 @@ const messages = defineMessages({
|
||||
id: 'project.about.creators.owner',
|
||||
defaultMessage: 'Project owner',
|
||||
},
|
||||
organization: {
|
||||
id: 'project.about.creators.organization',
|
||||
defaultMessage: 'Organization',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<div
|
||||
v-if="ipAddress"
|
||||
v-tooltip="`Copy Java IP: ${ipAddress}`"
|
||||
v-tooltip="formatMessage(messages.addressTooltip)"
|
||||
class="bg-button-bg flex gap-2 justify-between rounded-2xl items-center px-3 pr-1.5 h-12 cursor-pointer hover:bg-button-bg-hover hover:brightness-125 transition-all active:scale-95"
|
||||
@click="handleCopyIP"
|
||||
>
|
||||
@@ -17,7 +17,7 @@
|
||||
</div>
|
||||
|
||||
<section v-if="requiredContent" class="flex flex-col gap-2">
|
||||
<h3 class="text-primary text-base m-0">Required content</h3>
|
||||
<h3 class="text-primary text-base m-0">{{ formatMessage(messages.requiredContent) }}</h3>
|
||||
<ServerModpackContentCard
|
||||
:name="requiredContent.name"
|
||||
:version-number="requiredContent.versionNumber ?? ''"
|
||||
@@ -29,14 +29,16 @@
|
||||
/>
|
||||
</section>
|
||||
<section v-if="recommendedVersions.length" class="flex flex-col gap-2">
|
||||
<h3 class="text-primary text-base m-0">Minecraft: Java Edition</h3>
|
||||
<h3 class="text-primary text-base m-0">{{ formatMessage(messages.minecraftJava) }}</h3>
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
<TagItem
|
||||
v-for="version in formatVersionsForDisplay(recommendedVersions, tags.gameVersions)"
|
||||
:key="`recommended-tag-${version}`"
|
||||
>
|
||||
{{ version }}
|
||||
<template v-if="supportedVersions.length > 0"> (Recommended) </template>
|
||||
<template v-if="supportedVersions.length > 0">
|
||||
{{ formatMessage(messages.recommendedVersion) }}
|
||||
</template>
|
||||
</TagItem>
|
||||
<TagItem
|
||||
v-for="version in formatVersionsForDisplay(supportedVersionsList, tags.gameVersions)"
|
||||
@@ -56,7 +58,7 @@
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="props.ping !== undefined || region" class="flex flex-col gap-2">
|
||||
<h3 class="text-primary text-base m-0">Region</h3>
|
||||
<h3 class="text-primary text-base m-0">{{ formatMessage(messages.region) }}</h3>
|
||||
<div class="flex flex-wrap gap-1.5 items-center">
|
||||
<ServerPing
|
||||
v-if="projectV3?.status !== 'draft'"
|
||||
@@ -67,10 +69,10 @@
|
||||
</div>
|
||||
</section>
|
||||
<section v-if="languages.length > 0" class="flex flex-col gap-2">
|
||||
<h3 class="text-primary text-base m-0">Languages</h3>
|
||||
<h3 class="text-primary text-base m-0">{{ formatMessage(messages.languages) }}</h3>
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
<TagItem v-for="language in languages" :key="`${language}`">
|
||||
{{ languageDisplay.find((l) => l.value === language)?.label ?? language }}
|
||||
{{ SERVER_LANGUAGES[language] ? formatMessage(SERVER_LANGUAGES[language]) : language }}
|
||||
</TagItem>
|
||||
</div>
|
||||
</section>
|
||||
@@ -79,6 +81,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { CopyIcon, getLoaderIcon } from '@modrinth/assets'
|
||||
import { SERVER_LANGUAGES } from '@modrinth/ui'
|
||||
import { formatVersionsForDisplay, type GameVersionTag, type PlatformTag } from '@modrinth/utils'
|
||||
import { computed } from 'vue'
|
||||
|
||||
@@ -171,48 +174,6 @@ function handleCopyIP() {
|
||||
})
|
||||
}
|
||||
|
||||
const languageDisplay = [
|
||||
{ value: 'en', label: 'English' },
|
||||
{ value: 'es', label: 'Spanish' },
|
||||
{ value: 'pt', label: 'Portuguese' },
|
||||
{ value: 'fr', label: 'French' },
|
||||
{ value: 'de', label: 'German' },
|
||||
{ value: 'it', label: 'Italian' },
|
||||
{ value: 'nl', label: 'Dutch' },
|
||||
{ value: 'ru', label: 'Russian' },
|
||||
{ value: 'uk', label: 'Ukrainian' },
|
||||
{ value: 'pl', label: 'Polish' },
|
||||
{ value: 'cs', label: 'Czech' },
|
||||
{ value: 'sk', label: 'Slovak' },
|
||||
{ value: 'hu', label: 'Hungarian' },
|
||||
{ value: 'ro', label: 'Romanian' },
|
||||
{ value: 'bg', label: 'Bulgarian' },
|
||||
{ value: 'hr', label: 'Croatian' },
|
||||
{ value: 'sr', label: 'Serbian' },
|
||||
{ value: 'el', label: 'Greek' },
|
||||
{ value: 'tr', label: 'Turkish' },
|
||||
{ value: 'ar', label: 'Arabic' },
|
||||
{ value: 'he', label: 'Hebrew' },
|
||||
{ value: 'hi', label: 'Hindi' },
|
||||
{ value: 'bn', label: 'Bengali' },
|
||||
{ value: 'ur', label: 'Urdu' },
|
||||
{ value: 'zh', label: 'Chinese' },
|
||||
{ value: 'ja', label: 'Japanese' },
|
||||
{ value: 'ko', label: 'Korean' },
|
||||
{ value: 'th', label: 'Thai' },
|
||||
{ value: 'vi', label: 'Vietnamese' },
|
||||
{ value: 'id', label: 'Indonesian' },
|
||||
{ value: 'ms', label: 'Malay' },
|
||||
{ value: 'tl', label: 'Filipino' },
|
||||
{ value: 'sv', label: 'Swedish' },
|
||||
{ value: 'no', label: 'Norwegian' },
|
||||
{ value: 'da', label: 'Danish' },
|
||||
{ value: 'fi', label: 'Finnish' },
|
||||
{ value: 'lt', label: 'Lithuanian' },
|
||||
{ value: 'lv', label: 'Latvian' },
|
||||
{ value: 'et', label: 'Estonian' },
|
||||
]
|
||||
|
||||
const messages = defineMessages({
|
||||
copied: {
|
||||
id: `project.about.server.copied`,
|
||||
@@ -220,15 +181,35 @@ const messages = defineMessages({
|
||||
},
|
||||
copiedText: {
|
||||
id: `project.about.server.copiedText`,
|
||||
defaultMessage: 'IP address copied to clipboard',
|
||||
defaultMessage: 'Server address copied to clipboard',
|
||||
},
|
||||
title: {
|
||||
id: `project.about.server.title`,
|
||||
defaultMessage: 'Server details',
|
||||
},
|
||||
latency: {
|
||||
id: `project.about.server.latency`,
|
||||
defaultMessage: 'Latency',
|
||||
addressTooltip: {
|
||||
id: `project.about.server.address.tooltip`,
|
||||
defaultMessage: 'Copy Java server address',
|
||||
},
|
||||
requiredContent: {
|
||||
id: `project.about.server.requiredContent`,
|
||||
defaultMessage: 'Required content',
|
||||
},
|
||||
minecraftJava: {
|
||||
id: `project.about.compatibility.game.minecraftJava`,
|
||||
defaultMessage: 'Minecraft: Java Edition',
|
||||
},
|
||||
recommendedVersion: {
|
||||
id: `project.about.server.recommendedVersion`,
|
||||
defaultMessage: '(Recommended)',
|
||||
},
|
||||
region: {
|
||||
id: `project.about.server.region`,
|
||||
defaultMessage: 'Region',
|
||||
},
|
||||
languages: {
|
||||
id: `project.about.server.languages`,
|
||||
defaultMessage: 'Languages',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-if="allTags.length > 0" class="flex flex-col gap-3">
|
||||
<h2 class="text-lg m-0">Tags</h2>
|
||||
<h2 class="text-lg m-0">{{ formatMessage(messages.title) }}</h2>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<TagItem
|
||||
v-for="tag in allTags"
|
||||
@@ -16,6 +16,7 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import { defineMessages, useVIntl } from '../../composables'
|
||||
import FormattedTag from '../base/FormattedTag.vue'
|
||||
import TagItem from '../base/TagItem.vue'
|
||||
|
||||
@@ -42,6 +43,15 @@ const props = defineProps<{
|
||||
}
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
title: {
|
||||
id: 'project.about.tags.title',
|
||||
defaultMessage: 'Tags',
|
||||
},
|
||||
})
|
||||
|
||||
const allTags = computed(() => [
|
||||
...props.project.categories,
|
||||
...props.project.additional_categories,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
v-tooltip="showCustomModpackTooltip ? 'This project uses a custom modpack' : name"
|
||||
v-tooltip="showCustomModpackTooltip ? formatMessage(messages.customModpackTooltip) : name"
|
||||
class="flex gap-1.5 items-center flex-shrink overflow-hidden smart-clickable:allow-pointer-events"
|
||||
:class="[onclick ? 'hover:underline cursor-pointer' : '']"
|
||||
@click="onclick"
|
||||
@@ -13,6 +13,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineMessages, useVIntl } from '../../../composables'
|
||||
import Avatar from '../../base/Avatar.vue'
|
||||
|
||||
defineProps<{
|
||||
@@ -21,4 +22,13 @@ defineProps<{
|
||||
onclick?: () => void
|
||||
showCustomModpackTooltip?: boolean
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
customModpackTooltip: {
|
||||
id: `project.server.customModpackTooltip`,
|
||||
defaultMessage: 'This project uses a custom modpack',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Avatar :src="icon" size="34px" class="!rounded-xl !shadow-none" />
|
||||
<div class="flex flex-col items-start overflow-hidden">
|
||||
<div
|
||||
v-tooltip="showCustomModpackTooltip ? 'This project uses a custom modpack' : name"
|
||||
v-tooltip="showCustomModpackTooltip ? formatMessage(messages.customModpackTooltip) : name"
|
||||
class="truncate font-semibold text-sm max-w-full"
|
||||
:class="onclickName ? 'hover:underline cursor-pointer' : ''"
|
||||
@click="onclickName"
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<ButtonStyled v-if="onclickDownload" circular type="transparent">
|
||||
<button v-tooltip="'Download modpack'" @click="onclickDownload">
|
||||
<button v-tooltip="formatMessage(messages.downloadModpack)" @click="onclickDownload">
|
||||
<DownloadIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
@@ -32,6 +32,7 @@
|
||||
<script setup lang="ts">
|
||||
import { DownloadIcon } from '@modrinth/assets/generated-icons'
|
||||
|
||||
import { defineMessages, useVIntl } from '../../../composables'
|
||||
import Avatar from '../../base/Avatar.vue'
|
||||
import ButtonStyled from '../../base/ButtonStyled.vue'
|
||||
|
||||
@@ -44,4 +45,17 @@ defineProps<{
|
||||
onclickDownload?: () => void
|
||||
showCustomModpackTooltip?: boolean
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const messages = defineMessages({
|
||||
customModpackTooltip: {
|
||||
id: `project.server.customModpackTooltip`,
|
||||
defaultMessage: 'This project uses a custom modpack',
|
||||
},
|
||||
downloadModpack: {
|
||||
id: `project.about.server.downloadModpack`,
|
||||
defaultMessage: 'Download modpack',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { SignalIcon } from '@modrinth/assets'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { defineMessage, useVIntl } from '../../../composables'
|
||||
import { defineMessages, useVIntl } from '../../../composables'
|
||||
import { TagItem } from '../../base'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -10,9 +10,23 @@ const props = defineProps<{
|
||||
statusOnline?: boolean
|
||||
}>()
|
||||
|
||||
const pingMessage = defineMessage({
|
||||
id: 'project.server.ping.ms',
|
||||
defaultMessage: '{ping, number} ms',
|
||||
const messages = defineMessages({
|
||||
ping: {
|
||||
id: 'project.server.ping.ms',
|
||||
defaultMessage: '{ping, number} ms',
|
||||
},
|
||||
online: {
|
||||
id: 'project.server.status.online',
|
||||
defaultMessage: 'Online',
|
||||
},
|
||||
offline: {
|
||||
id: 'project.server.status.offline',
|
||||
defaultMessage: 'Offline',
|
||||
},
|
||||
offlineTooltip: {
|
||||
id: 'project.server.status.offline.tooltip',
|
||||
defaultMessage: 'Server is offline',
|
||||
},
|
||||
})
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
@@ -37,19 +51,19 @@ const pingClass = computed(() => {
|
||||
:class="pingClass"
|
||||
>
|
||||
<template v-if="ping !== undefined">
|
||||
{{ formatMessage(pingMessage, { ping }) }}
|
||||
{{ formatMessage(messages.ping, { ping }) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<SignalIcon />
|
||||
Online
|
||||
{{ formatMessage(messages.online) }}
|
||||
</template>
|
||||
</TagItem>
|
||||
<TagItem
|
||||
v-else
|
||||
v-tooltip="'Server is offline'"
|
||||
v-tooltip="formatMessage(messages.offlineTooltip)"
|
||||
class="border !border-solid border-red bg-highlight-red text-red smart-clickable:allow-pointer-events w-max"
|
||||
>
|
||||
<SignalIcon />
|
||||
Offline
|
||||
{{ formatMessage(messages.offline) }}
|
||||
</TagItem>
|
||||
</template>
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { defineMessage, useVIntl } from '../../../composables'
|
||||
import { SERVER_REGIONS } from '../../../utils'
|
||||
import { TagItem } from '../../base'
|
||||
|
||||
const { region } = defineProps<{
|
||||
region: string
|
||||
}>()
|
||||
|
||||
const regionNames: Record<string, string> = {
|
||||
us_east: 'US East',
|
||||
us_west: 'US West',
|
||||
europe: 'Europe',
|
||||
asia: 'Asia',
|
||||
australia: 'Australia',
|
||||
south_america: 'South America',
|
||||
middle_east: 'Middle East',
|
||||
russia: 'Russia',
|
||||
}
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const regionName = computed(() => regionNames[region] ?? region)
|
||||
const tooltip = defineMessage({
|
||||
id: 'project.server.region.tooltip',
|
||||
defaultMessage: 'Server hosted in {regionName}',
|
||||
})
|
||||
|
||||
const regionName = computed(() => {
|
||||
const name = SERVER_REGIONS[region]
|
||||
if (name) return formatMessage(name)
|
||||
|
||||
return region
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<TagItem v-tooltip="`Server hosted in ${regionName}`">{{ regionName }}</TagItem>
|
||||
<TagItem v-tooltip="formatMessage(tooltip, { regionName })">{{ regionName }}</TagItem>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user