Make tags translatable, move icons to frontend, a few other things (#5229)

* Make tags translatable, move icons to frontend, a few other things

* Migrate more things

* fix import

* more import fixes

* export tag-messages

* lint
This commit is contained in:
Prospector
2026-01-28 11:01:56 -08:00
committed by GitHub
parent 6d68d50699
commit 16ac2aae6b
121 changed files with 1532 additions and 229 deletions

View File

@@ -0,0 +1,19 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useVIntl } from '../../composables'
import { getTagMessageOrDefault } from '../../utils/tag-messages.ts'
const { formatMessage } = useVIntl()
const props = defineProps<{
tag: string
enforceType?: 'loader' | 'category'
}>()
const message = computed(() => getTagMessageOrDefault(props.tag, props.enforceType))
</script>
<template>
{{ typeof message === 'string' ? message : formatMessage(message) }}
</template>

View File

@@ -69,14 +69,13 @@
<script setup>
import { CalendarIcon, DownloadIcon, EditIcon, HeartIcon } from '@modrinth/assets'
import { Avatar, Categories } from '@modrinth/ui'
import { formatNumber } from '@modrinth/utils'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime.js'
import { computed } from 'vue'
import { useRelativeTime } from '../../composables'
import Categories from '../search/Categories.vue'
import Avatar from './Avatar.vue'
import EnvironmentIndicator from './EnvironmentIndicator.vue'
import Badge from './SimpleBadge.vue'

View File

@@ -0,0 +1,21 @@
<script setup lang="ts">
import { getCategoryIcon, getLoaderIcon, getTagIcon } from '@modrinth/assets'
import { computed } from 'vue'
const props = defineProps<{
tag: string
enforceType?: 'loader' | 'category'
}>()
const icon = computed(() =>
props.enforceType === 'loader'
? getLoaderIcon(props.tag)
: props.enforceType === 'category'
? getCategoryIcon(props.tag)
: getTagIcon(props.tag),
)
</script>
<template>
<component :is="icon" v-if="icon" />
</template>

View File

@@ -28,6 +28,7 @@ export type { FilterBarOption } from './FilterBar.vue'
export { default as FilterBar } from './FilterBar.vue'
export { default as FloatingActionBar } from './FloatingActionBar.vue'
export { default as FloatingPanel } from './FloatingPanel.vue'
export { default as FormattedTag } from './FormattedTag.vue'
export { default as HeadingLink } from './HeadingLink.vue'
export { default as HorizontalRule } from './HorizontalRule.vue'
export { default as IconSelect } from './IconSelect.vue'

View File

@@ -20,7 +20,7 @@
:key="tag"
class="text-sm font-semibold text-secondary flex gap-1 px-[0.375rem] py-0.5 bg-button-bg rounded-full"
>
{{ formatCategory(tag) }}
<FormattedTag :tag="tag" />
</div>
</div>
</div>
@@ -65,10 +65,10 @@
<script setup>
import { DownloadIcon, HeartIcon, HistoryIcon, TagsIcon } from '@modrinth/assets'
import { formatCategory, formatNumber } from '@modrinth/utils'
import { Avatar, FormattedTag } from '@modrinth/ui'
import { formatNumber } from '@modrinth/utils'
import { useRelativeTime } from '../../composables'
import Avatar from '../base/Avatar.vue'
const formatRelativeTime = useRelativeTime()

View File

@@ -42,7 +42,7 @@
:key="index"
:action="() => router.push(`/${project.project_type}s?f=categories:${category}`)"
>
{{ formatCategory(category) }}
<FormattedTag :tag="category" />
</TagItem>
</div>
</div>
@@ -54,11 +54,12 @@
</template>
<script setup lang="ts">
import { DownloadIcon, HeartIcon, TagsIcon } from '@modrinth/assets'
import { formatCategory, formatNumber, type Project } from '@modrinth/utils'
import { formatNumber, type Project } from '@modrinth/utils'
import { useRouter } from 'vue-router'
import Avatar from '../base/Avatar.vue'
import ContentPageHeader from '../base/ContentPageHeader.vue'
import FormattedTag from '../base/FormattedTag.vue'
import TagItem from '../base/TagItem.vue'
import ProjectStatusBadge from './ProjectStatusBadge.vue'

View File

@@ -149,9 +149,8 @@
:style="`--_color: var(--color-platform-${platform})`"
:action="() => versionFilters?.toggleFilter('platform', platform)"
>
<!-- eslint-disable-next-line vue/no-v-html -->
<svg v-html="loaders.find((x) => x.name === platform)?.icon"></svg>
{{ formatCategory(platform) }}
<component :is="getLoaderIcon(platform)" v-if="getLoaderIcon(platform)" />
<FormattedTag :tag="platform" enforce-type="loader" />
</TagItem>
</div>
</div>
@@ -221,11 +220,18 @@
</template>
<script setup lang="ts">
import type { Labrinth } from '@modrinth/api-client'
import { CalendarIcon, DownloadIcon, PlusIcon, StarIcon } from '@modrinth/assets'
import { ButtonStyled } from '@modrinth/ui'
import { CalendarIcon, DownloadIcon, getLoaderIcon, PlusIcon, StarIcon } from '@modrinth/assets'
import {
AutoLink,
ButtonStyled,
FormattedTag,
Pagination,
TagItem,
VersionChannelIndicator,
VersionFilterControl,
} from '@modrinth/ui'
import {
formatBytes,
formatCategory,
formatNumber,
formatVersionsForDisplay,
type GameVersionTag,
@@ -237,9 +243,6 @@ import { useRoute, useRouter } from 'vue-router'
import { useRelativeTime } from '../../composables'
import { useVIntl } from '../../composables/i18n'
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 { getEnvironmentTags } from './settings/environment/environments'
const { formatMessage } = useVIntl()

View File

@@ -21,8 +21,8 @@
: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>
{{ formatCategory(platform) }}
<component :is="getLoaderIcon(platform)" v-if="getLoaderIcon(platform)" />
<FormattedTag :tag="platform" enforce-type="loader" />
</TagItem>
</div>
</section>
@@ -85,9 +85,16 @@
</div>
</template>
<script setup lang="ts">
import { ClientIcon, MonitorSmartphoneIcon, ServerIcon, UserIcon } from '@modrinth/assets'
import {
ClientIcon,
getLoaderIcon,
MonitorSmartphoneIcon,
ServerIcon,
UserIcon,
} from '@modrinth/assets'
import { FormattedTag, TagItem } from '@modrinth/ui'
import type { EnvironmentV3, GameVersionTag, PlatformTag, ProjectV3Partial } from '@modrinth/utils'
import { formatCategory, getVersionsToDisplay } from '@modrinth/utils'
import { getVersionsToDisplay } from '@modrinth/utils'
import { type Component, computed } from 'vue'
import { useRouter } from 'vue-router'
@@ -97,7 +104,6 @@ import {
type MessageDescriptor,
useVIntl,
} from '../../composables/i18n'
import TagItem from '../base/TagItem.vue'
const { formatMessage } = useVIntl()
const router = useRouter()

View File

@@ -33,13 +33,13 @@
>
<CalendarIcon aria-hidden="true" />
<div>
{{ formatMessage(messages.published, { date: publishedDate }) }}
{{ capitalizeString(formatMessage(messages.published, { date: publishedDate })) }}
</div>
</div>
<div v-else v-tooltip="dayjs(project.published).format('MMMM D, YYYY [at] h:mm A')">
<CalendarIcon aria-hidden="true" />
<div>
{{ formatMessage(messages.created, { date: createdDate }) }}
{{ capitalizeString(formatMessage(messages.created, { date: createdDate })) }}
</div>
</div>
<div
@@ -48,7 +48,7 @@
>
<ScaleIcon aria-hidden="true" />
<div>
{{ formatMessage(messages.submitted, { date: submittedDate }) }}
{{ capitalizeString(formatMessage(messages.submitted, { date: submittedDate })) }}
</div>
</div>
<div
@@ -57,7 +57,7 @@
>
<VersionIcon aria-hidden="true" />
<div>
{{ formatMessage(messages.updated, { date: updatedDate }) }}
{{ capitalizeString(formatMessage(messages.updated, { date: updatedDate })) }}
</div>
</div>
</div>
@@ -65,6 +65,7 @@
</template>
<script setup lang="ts">
import { BookTextIcon, CalendarIcon, ExternalIcon, ScaleIcon, VersionIcon } from '@modrinth/assets'
import { capitalizeString } from '@modrinth/utils'
import dayjs from 'dayjs'
import { computed } from 'vue'

View File

@@ -1,24 +1,28 @@
<template>
<div class="categories">
<slot />
<span
v-for="category in categories"
:key="category.name"
v-html="category.icon + formatCategory(category.name)"
/>
<span v-for="category in categories.filter((x) => !!x)" :key="category">
<component :is="getTagIcon(category)" v-if="getTagIcon(category)" />
{{ getFormattedMessage(category) }}
</span>
</div>
</template>
<script setup>
import { formatCategory } from '@modrinth/utils'
<script setup lang="ts">
import { getTagIcon } from '@modrinth/assets'
defineProps({
categories: {
type: Array,
default() {
return []
},
},
})
import { useVIntl } from '../../composables'
import { getTagMessageOrDefault } from '../../utils/tag-messages.ts'
const { formatMessage } = useVIntl()
defineProps<{
categories: string[]
}>()
const getFormattedMessage = (tag: string) => {
const message = getTagMessageOrDefault(tag)
return typeof message === 'string' ? message : formatMessage(message)
}
</script>
<style lang="scss" scoped>

View File

@@ -10,7 +10,7 @@
<FilterIcon class="h-5 w-5 text-secondary" />
Platform
<template #option="{ option }">
{{ formatCategory(option) }}
<FormattedTag :tag="option" enforce-type="loader" />
</template>
</ManySelect>
<ManySelect
@@ -72,7 +72,7 @@
:action="() => toggleFilter('platform', platform)"
>
<XIcon />
{{ formatCategory(platform) }}
<FormattedTag :tag="platform" enforce-type="loader" />
</TagItem>
</div>
</div>
@@ -80,13 +80,11 @@
<script setup lang="ts">
import { FilterIcon, XCircleIcon, XIcon } from '@modrinth/assets'
import { formatCategory, type GameVersionTag, type Version } from '@modrinth/utils'
import { Checkbox, FormattedTag, ManySelect, TagItem } from '@modrinth/ui'
import type { GameVersionTag, Version } from '@modrinth/utils'
import { computed, ref } from 'vue'
import { useRoute } from 'vue-router'
import TagItem from '../base/TagItem.vue'
import { Checkbox, ManySelect } from '../index'
const props = defineProps<{
versions: Version[]
gameVersions: GameVersionTag[]

View File

@@ -1235,6 +1235,291 @@
"settings.sessions.title": {
"defaultMessage": "Sessions"
},
"tag.category.128x": {
"defaultMessage": "128x"
},
"tag.category.16x": {
"defaultMessage": "16x"
},
"tag.category.256x": {
"defaultMessage": "256x"
},
"tag.category.32x": {
"defaultMessage": "32x"
},
"tag.category.48x": {
"defaultMessage": "48x"
},
"tag.category.512x+": {
"defaultMessage": "512x or higher"
},
"tag.category.64x": {
"defaultMessage": "64x"
},
"tag.category.8x-": {
"defaultMessage": "8x or lower"
},
"tag.category.adventure": {
"defaultMessage": "Adventure"
},
"tag.category.atmosphere": {
"defaultMessage": "Atmosphere"
},
"tag.category.audio": {
"defaultMessage": "Audio"
},
"tag.category.blocks": {
"defaultMessage": "Blocks"
},
"tag.category.bloom": {
"defaultMessage": "Bloom"
},
"tag.category.cartoon": {
"defaultMessage": "Cartoon"
},
"tag.category.challenging": {
"defaultMessage": "Challenging"
},
"tag.category.colored-lighting": {
"defaultMessage": "Colored Lighting"
},
"tag.category.combat": {
"defaultMessage": "Combat"
},
"tag.category.core-shaders": {
"defaultMessage": "Core Shaders"
},
"tag.category.cursed": {
"defaultMessage": "Cursed"
},
"tag.category.decoration": {
"defaultMessage": "Decoration"
},
"tag.category.economy": {
"defaultMessage": "Economy"
},
"tag.category.entities": {
"defaultMessage": "Entities"
},
"tag.category.environment": {
"defaultMessage": "Environment"
},
"tag.category.equipment": {
"defaultMessage": "Equipment"
},
"tag.category.fantasy": {
"defaultMessage": "Fantasy"
},
"tag.category.foliage": {
"defaultMessage": "Foliage"
},
"tag.category.fonts": {
"defaultMessage": "Fonts"
},
"tag.category.food": {
"defaultMessage": "Food"
},
"tag.category.game-mechanics": {
"defaultMessage": "Game Mechanics"
},
"tag.category.gui": {
"defaultMessage": "GUI"
},
"tag.category.high": {
"defaultMessage": "High"
},
"tag.category.items": {
"defaultMessage": "Items"
},
"tag.category.kitchen-sink": {
"defaultMessage": "Kitchen Sink"
},
"tag.category.library": {
"defaultMessage": "Library"
},
"tag.category.lightweight": {
"defaultMessage": "Lightweight"
},
"tag.category.locale": {
"defaultMessage": "Locale"
},
"tag.category.low": {
"defaultMessage": "Low"
},
"tag.category.magic": {
"defaultMessage": "Magic"
},
"tag.category.management": {
"defaultMessage": "Management"
},
"tag.category.medium": {
"defaultMessage": "Medium"
},
"tag.category.minigame": {
"defaultMessage": "Minigame"
},
"tag.category.mobs": {
"defaultMessage": "Mobs"
},
"tag.category.modded": {
"defaultMessage": "Modded"
},
"tag.category.models": {
"defaultMessage": "Models"
},
"tag.category.multiplayer": {
"defaultMessage": "Multiplayer"
},
"tag.category.optimization": {
"defaultMessage": "Optimization"
},
"tag.category.path-tracing": {
"defaultMessage": "Path Tracing"
},
"tag.category.pbr": {
"defaultMessage": "PBR"
},
"tag.category.potato": {
"defaultMessage": "Potato"
},
"tag.category.quests": {
"defaultMessage": "Quests"
},
"tag.category.realistic": {
"defaultMessage": "Realistic"
},
"tag.category.reflections": {
"defaultMessage": "Reflections"
},
"tag.category.screenshot": {
"defaultMessage": "Screenshot"
},
"tag.category.semi-realistic": {
"defaultMessage": "Semi Realistic"
},
"tag.category.shadows": {
"defaultMessage": "Shadows"
},
"tag.category.simplistic": {
"defaultMessage": "Simplistic"
},
"tag.category.social": {
"defaultMessage": "Social"
},
"tag.category.storage": {
"defaultMessage": "Storage"
},
"tag.category.technology": {
"defaultMessage": "Technology"
},
"tag.category.themed": {
"defaultMessage": "Themed"
},
"tag.category.transportation": {
"defaultMessage": "Transportation"
},
"tag.category.tweaks": {
"defaultMessage": "Tweaks"
},
"tag.category.utility": {
"defaultMessage": "Utility"
},
"tag.category.vanilla-like": {
"defaultMessage": "Vanilla Like"
},
"tag.category.worldgen": {
"defaultMessage": "World Generation"
},
"tag.loader.babric": {
"defaultMessage": "Babric"
},
"tag.loader.bta-babric": {
"defaultMessage": "BTA (Babric)"
},
"tag.loader.bukkit": {
"defaultMessage": "Bukkit"
},
"tag.loader.bungeecord": {
"defaultMessage": "BungeeCord"
},
"tag.loader.canvas": {
"defaultMessage": "Canvas"
},
"tag.loader.datapack": {
"defaultMessage": "Data Pack"
},
"tag.loader.fabric": {
"defaultMessage": "Fabric"
},
"tag.loader.folia": {
"defaultMessage": "Folia"
},
"tag.loader.forge": {
"defaultMessage": "Forge"
},
"tag.loader.geyser": {
"defaultMessage": "Geyser Extension"
},
"tag.loader.iris": {
"defaultMessage": "Iris"
},
"tag.loader.java-agent": {
"defaultMessage": "Java Agent"
},
"tag.loader.legacy-fabric": {
"defaultMessage": "Legacy Fabric"
},
"tag.loader.liteloader": {
"defaultMessage": "LiteLoader"
},
"tag.loader.minecraft": {
"defaultMessage": "Resource Pack"
},
"tag.loader.modloader": {
"defaultMessage": "Risugami's ModLoader"
},
"tag.loader.mrpack": {
"defaultMessage": "Modpack"
},
"tag.loader.neoforge": {
"defaultMessage": "NeoForge"
},
"tag.loader.nilloader": {
"defaultMessage": "NilLoader"
},
"tag.loader.optifine": {
"defaultMessage": "OptiFine"
},
"tag.loader.ornithe": {
"defaultMessage": "Ornithe"
},
"tag.loader.paper": {
"defaultMessage": "Paper"
},
"tag.loader.purpur": {
"defaultMessage": "Purpur"
},
"tag.loader.quilt": {
"defaultMessage": "Quilt"
},
"tag.loader.rift": {
"defaultMessage": "Rift"
},
"tag.loader.spigot": {
"defaultMessage": "Spigot"
},
"tag.loader.sponge": {
"defaultMessage": "Sponge"
},
"tag.loader.vanilla": {
"defaultMessage": "Vanilla Shader"
},
"tag.loader.velocity": {
"defaultMessage": "Velocity"
},
"tag.loader.waterfall": {
"defaultMessage": "Waterfall"
},
"tooltip.date-at-time": {
"defaultMessage": "{date, date, long} at {time, time, short}"
},

View File

@@ -6,4 +6,5 @@ export * from './game-modes'
export * from './notices'
export * from './savable'
export * from './search'
export * from './tag-messages'
export * from './vue-children'

View File

@@ -1,10 +1,11 @@
import type { Labrinth } from '@modrinth/api-client'
import { ClientIcon, ServerIcon } from '@modrinth/assets'
import { formatCategory, formatCategoryHeader, sortByNameOrNumber } from '@modrinth/utils'
import { ClientIcon, getCategoryIcon, getLoaderIcon, ServerIcon } from '@modrinth/assets'
import { formatCategoryHeader, sortByNameOrNumber } from '@modrinth/utils'
import { type Component, computed, readonly, type Ref, ref } from 'vue'
import { type LocationQueryRaw, type LocationQueryValue, useRoute } from 'vue-router'
import { defineMessage, useVIntl } from '../composables/i18n'
import { getTagMessageOrDefault } from './tag-messages.ts'
type BaseOption = {
id: string
@@ -111,7 +112,22 @@ export function useSearch(
const filters = computed(() => {
const categoryFilters: Record<string, FilterType> = {}
for (const category of sortByNameOrNumber(tags.value.categories.slice(), ['header', 'name'])) {
const sortedCategories = sortByNameOrNumber(tags.value.categories.slice(), ['header', 'name'])
sortedCategories.sort((a, b) => {
if (a.header === 'performance impact' && b.header === 'performance impact') {
const qualityOrder = ['potato', 'low', 'medium', 'high', 'screenshot']
const aIndex = qualityOrder.indexOf(a.name)
const bIndex = qualityOrder.indexOf(b.name)
if (aIndex !== -1 && bIndex !== -1) {
return aIndex - bIndex
}
if (aIndex !== -1) return -1
if (bIndex !== -1) return 1
}
return 0
})
for (const category of sortedCategories) {
const filterTypeId = `category_${category.project_type}_${category.header}`
if (!categoryFilters[filterTypeId]) {
categoryFilters[filterTypeId] = {
@@ -120,7 +136,7 @@ export function useSearch(
supported_project_types:
category.project_type === 'mod'
? ['mod', 'plugin', 'datapack']
: [category.project_type],
: ([category.project_type] as ProjectType[]),
display: 'all',
query_param: category.header === 'resolutions' ? 'g' : 'f',
supports_negative_filter: true,
@@ -128,10 +144,11 @@ export function useSearch(
options: [],
}
}
const message = getTagMessageOrDefault(category.name, 'category')
categoryFilters[filterTypeId].options.push({
id: category.name,
formatted_name: formatCategory(category.name),
icon: category.icon,
formatted_name: typeof message === 'string' ? message : formatMessage(message),
icon: getCategoryIcon(category.name),
value: `categories:${category.name}`,
method: category.header === 'resolutions' ? 'or' : 'and',
})
@@ -225,7 +242,7 @@ export function useSearch(
display: 'expandable',
query_param: 'g',
supports_negative_filter: true,
default_values: ['fabric', 'forge', 'neoforge', 'quilt'],
default_values: ['fabric', 'forge', 'neoforge'],
searchable: false,
options: tags.value.loaders
.filter(
@@ -235,10 +252,11 @@ export function useSearch(
!loader.supported_project_types.includes('datapack'),
)
.map((loader) => {
const message = getTagMessageOrDefault(loader.name, 'loader')
return {
id: loader.name,
formatted_name: formatCategory(loader.name),
icon: loader.icon,
formatted_name: typeof message === 'string' ? message : formatMessage(message),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
@@ -261,10 +279,11 @@ export function useSearch(
options: tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('modpack'))
.map((loader) => {
const message = getTagMessageOrDefault(loader.name, 'loader')
return {
id: loader.name,
formatted_name: formatCategory(loader.name),
icon: loader.icon,
formatted_name: typeof message === 'string' ? message : formatMessage(message),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
@@ -290,10 +309,11 @@ export function useSearch(
!PLUGIN_PLATFORMS.includes(loader.name),
)
.map((loader) => {
const message = getTagMessageOrDefault(loader.name, 'loader')
return {
id: loader.name,
formatted_name: formatCategory(loader.name),
icon: loader.icon,
formatted_name: typeof message === 'string' ? message : formatMessage(message),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
@@ -315,10 +335,11 @@ export function useSearch(
options: tags.value.loaders
.filter((loader) => PLUGIN_PLATFORMS.includes(loader.name))
.map((loader) => {
const message = getTagMessageOrDefault(loader.name, 'loader')
return {
id: loader.name,
formatted_name: formatCategory(loader.name),
icon: loader.icon,
formatted_name: typeof message === 'string' ? message : formatMessage(message),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}
@@ -333,17 +354,19 @@ export function useSearch(
}),
),
supported_project_types: ['shader'],
display: 'all',
query_param: 'g',
supports_negative_filter: true,
searchable: false,
display: 'expandable',
default_values: ['iris', 'optifine', 'vanilla'],
options: tags.value.loaders
.filter((loader) => loader.supported_project_types.includes('shader'))
.map((loader) => {
const message = getTagMessageOrDefault(loader.name, 'loader')
return {
id: loader.name,
formatted_name: formatCategory(loader.name),
icon: loader.icon,
formatted_name: typeof message === 'string' ? message : formatMessage(message),
icon: getLoaderIcon(loader.name),
method: 'or',
value: `categories:${loader.name}`,
}

View File

@@ -0,0 +1,409 @@
import { capitalizeString } from '@modrinth/utils'
import { defineMessages, type MessageDescriptor } from '../composables/i18n'
export const loaderMessages = defineMessages({
babric: {
id: 'tag.loader.babric',
defaultMessage: 'Babric',
},
'bta-babric': {
id: 'tag.loader.bta-babric',
defaultMessage: 'BTA (Babric)',
},
bukkit: {
id: 'tag.loader.bukkit',
defaultMessage: 'Bukkit',
},
bungeecord: {
id: 'tag.loader.bungeecord',
defaultMessage: 'BungeeCord',
},
canvas: {
id: 'tag.loader.canvas',
defaultMessage: 'Canvas',
},
datapack: {
id: 'tag.loader.datapack',
defaultMessage: 'Data Pack',
},
fabric: {
id: 'tag.loader.fabric',
defaultMessage: 'Fabric',
},
folia: {
id: 'tag.loader.folia',
defaultMessage: 'Folia',
},
forge: {
id: 'tag.loader.forge',
defaultMessage: 'Forge',
},
geyser: {
id: 'tag.loader.geyser',
defaultMessage: 'Geyser Extension',
},
iris: {
id: 'tag.loader.iris',
defaultMessage: 'Iris',
},
'java-agent': {
id: 'tag.loader.java-agent',
defaultMessage: 'Java Agent',
},
'legacy-fabric': {
id: 'tag.loader.legacy-fabric',
defaultMessage: 'Legacy Fabric',
},
liteloader: {
id: 'tag.loader.liteloader',
defaultMessage: 'LiteLoader',
},
minecraft: {
id: 'tag.loader.minecraft',
defaultMessage: 'Resource Pack',
},
modloader: {
id: 'tag.loader.modloader',
defaultMessage: "Risugami's ModLoader",
},
mrpack: {
id: 'tag.loader.mrpack',
defaultMessage: 'Modpack',
},
neoforge: {
id: 'tag.loader.neoforge',
defaultMessage: 'NeoForge',
},
nilloader: {
id: 'tag.loader.nilloader',
defaultMessage: 'NilLoader',
},
optifine: {
id: 'tag.loader.optifine',
defaultMessage: 'OptiFine',
},
ornithe: {
id: 'tag.loader.ornithe',
defaultMessage: 'Ornithe',
},
paper: {
id: 'tag.loader.paper',
defaultMessage: 'Paper',
},
purpur: {
id: 'tag.loader.purpur',
defaultMessage: 'Purpur',
},
quilt: {
id: 'tag.loader.quilt',
defaultMessage: 'Quilt',
},
rift: {
id: 'tag.loader.rift',
defaultMessage: 'Rift',
},
spigot: {
id: 'tag.loader.spigot',
defaultMessage: 'Spigot',
},
sponge: {
id: 'tag.loader.sponge',
defaultMessage: 'Sponge',
},
vanilla: {
id: 'tag.loader.vanilla',
defaultMessage: 'Vanilla Shader',
},
velocity: {
id: 'tag.loader.velocity',
defaultMessage: 'Velocity',
},
waterfall: {
id: 'tag.loader.waterfall',
defaultMessage: 'Waterfall',
},
})
export const categoryMessages = defineMessages({
'128x': {
id: 'tag.category.128x',
defaultMessage: '128x',
},
'16x': {
id: 'tag.category.16x',
defaultMessage: '16x',
},
'256x': {
id: 'tag.category.256x',
defaultMessage: '256x',
},
'32x': {
id: 'tag.category.32x',
defaultMessage: '32x',
},
'48x': {
id: 'tag.category.48x',
defaultMessage: '48x',
},
'512x+': {
id: 'tag.category.512x+',
defaultMessage: '512x or higher',
},
'64x': {
id: 'tag.category.64x',
defaultMessage: '64x',
},
'8x-': {
id: 'tag.category.8x-',
defaultMessage: '8x or lower',
},
adventure: {
id: 'tag.category.adventure',
defaultMessage: 'Adventure',
},
atmosphere: {
id: 'tag.category.atmosphere',
defaultMessage: 'Atmosphere',
},
audio: {
id: 'tag.category.audio',
defaultMessage: 'Audio',
},
blocks: {
id: 'tag.category.blocks',
defaultMessage: 'Blocks',
},
bloom: {
id: 'tag.category.bloom',
defaultMessage: 'Bloom',
},
cartoon: {
id: 'tag.category.cartoon',
defaultMessage: 'Cartoon',
},
challenging: {
id: 'tag.category.challenging',
defaultMessage: 'Challenging',
},
'colored-lighting': {
id: 'tag.category.colored-lighting',
defaultMessage: 'Colored Lighting',
},
combat: {
id: 'tag.category.combat',
defaultMessage: 'Combat',
},
'core-shaders': {
id: 'tag.category.core-shaders',
defaultMessage: 'Core Shaders',
},
cursed: {
id: 'tag.category.cursed',
defaultMessage: 'Cursed',
},
decoration: {
id: 'tag.category.decoration',
defaultMessage: 'Decoration',
},
economy: {
id: 'tag.category.economy',
defaultMessage: 'Economy',
},
entities: {
id: 'tag.category.entities',
defaultMessage: 'Entities',
},
environment: {
id: 'tag.category.environment',
defaultMessage: 'Environment',
},
equipment: {
id: 'tag.category.equipment',
defaultMessage: 'Equipment',
},
fantasy: {
id: 'tag.category.fantasy',
defaultMessage: 'Fantasy',
},
foliage: {
id: 'tag.category.foliage',
defaultMessage: 'Foliage',
},
fonts: {
id: 'tag.category.fonts',
defaultMessage: 'Fonts',
},
food: {
id: 'tag.category.food',
defaultMessage: 'Food',
},
'game-mechanics': {
id: 'tag.category.game-mechanics',
defaultMessage: 'Game Mechanics',
},
gui: {
id: 'tag.category.gui',
defaultMessage: 'GUI',
},
high: {
id: 'tag.category.high',
defaultMessage: 'High',
},
items: {
id: 'tag.category.items',
defaultMessage: 'Items',
},
'kitchen-sink': {
id: 'tag.category.kitchen-sink',
defaultMessage: 'Kitchen Sink',
},
library: {
id: 'tag.category.library',
defaultMessage: 'Library',
},
lightweight: {
id: 'tag.category.lightweight',
defaultMessage: 'Lightweight',
},
locale: {
id: 'tag.category.locale',
defaultMessage: 'Locale',
},
low: {
id: 'tag.category.low',
defaultMessage: 'Low',
},
magic: {
id: 'tag.category.magic',
defaultMessage: 'Magic',
},
management: {
id: 'tag.category.management',
defaultMessage: 'Management',
},
medium: {
id: 'tag.category.medium',
defaultMessage: 'Medium',
},
minigame: {
id: 'tag.category.minigame',
defaultMessage: 'Minigame',
},
mobs: {
id: 'tag.category.mobs',
defaultMessage: 'Mobs',
},
modded: {
id: 'tag.category.modded',
defaultMessage: 'Modded',
},
models: {
id: 'tag.category.models',
defaultMessage: 'Models',
},
multiplayer: {
id: 'tag.category.multiplayer',
defaultMessage: 'Multiplayer',
},
optimization: {
id: 'tag.category.optimization',
defaultMessage: 'Optimization',
},
'path-tracing': {
id: 'tag.category.path-tracing',
defaultMessage: 'Path Tracing',
},
pbr: {
id: 'tag.category.pbr',
defaultMessage: 'PBR',
},
potato: {
id: 'tag.category.potato',
defaultMessage: 'Potato',
},
quests: {
id: 'tag.category.quests',
defaultMessage: 'Quests',
},
realistic: {
id: 'tag.category.realistic',
defaultMessage: 'Realistic',
},
reflections: {
id: 'tag.category.reflections',
defaultMessage: 'Reflections',
},
screenshot: {
id: 'tag.category.screenshot',
defaultMessage: 'Screenshot',
},
'semi-realistic': {
id: 'tag.category.semi-realistic',
defaultMessage: 'Semi Realistic',
},
shadows: {
id: 'tag.category.shadows',
defaultMessage: 'Shadows',
},
simplistic: {
id: 'tag.category.simplistic',
defaultMessage: 'Simplistic',
},
social: {
id: 'tag.category.social',
defaultMessage: 'Social',
},
storage: {
id: 'tag.category.storage',
defaultMessage: 'Storage',
},
technology: {
id: 'tag.category.technology',
defaultMessage: 'Technology',
},
themed: {
id: 'tag.category.themed',
defaultMessage: 'Themed',
},
transportation: {
id: 'tag.category.transportation',
defaultMessage: 'Transportation',
},
tweaks: {
id: 'tag.category.tweaks',
defaultMessage: 'Tweaks',
},
utility: {
id: 'tag.category.utility',
defaultMessage: 'Utility',
},
'vanilla-like': {
id: 'tag.category.vanilla-like',
defaultMessage: 'Vanilla Like',
},
worldgen: {
id: 'tag.category.worldgen',
defaultMessage: 'World Generation',
},
})
export function getTagMessage(
tag: string,
enforceType?: 'loader' | 'category',
): MessageDescriptor | undefined {
if (enforceType === 'loader') {
return loaderMessages[tag]
} else if (enforceType === 'category') {
return categoryMessages[tag]
} else {
return loaderMessages[tag] ?? categoryMessages[tag]
}
}
export function getTagMessageOrDefault(
tag: string,
enforceType?: 'loader' | 'category',
): MessageDescriptor | string {
return getTagMessage(tag, enforceType) ?? capitalizeString(tag)
}