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:
@@ -1,97 +1,105 @@
|
||||
import { getCategoryIcon, SERVER_CATEGORY_ICON_MAP } from '@modrinth/assets'
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { getCategoryIcon, GlobeIcon, SERVER_CATEGORY_ICON_MAP, UserIcon } from '@modrinth/assets'
|
||||
import { sortedCategories } from '@modrinth/utils'
|
||||
import { computed, type Ref, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { useVIntl } from '../composables/i18n'
|
||||
import { defineMessage, LOCALES, useVIntl } from '../composables/i18n'
|
||||
import type { FilterType, FilterValue, SortType, Tags } from './search'
|
||||
import { formatCategory, formatCategoryHeader } from './tag-messages'
|
||||
|
||||
export const SERVER_REGIONS = [
|
||||
{ code: 'us_east', name: 'US East' },
|
||||
{ code: 'us_west', name: 'US West' },
|
||||
{ code: 'europe', name: 'Europe' },
|
||||
{ code: 'asia', name: 'Asia' },
|
||||
{ code: 'australia', name: 'Australia' },
|
||||
{ code: 'south_america', name: 'South America' },
|
||||
{ code: 'middle_east', name: 'Middle East' },
|
||||
{ code: 'russia', name: 'Russia' },
|
||||
]
|
||||
export const SERVER_REGIONS = {
|
||||
us_east: defineMessage({ id: 'project.server.region.us_east', defaultMessage: 'US East' }),
|
||||
us_west: defineMessage({ id: 'project.server.region.us_west', defaultMessage: 'US West' }),
|
||||
europe: defineMessage({ id: 'project.server.region.europe', defaultMessage: 'Europe' }),
|
||||
asia: defineMessage({ id: 'project.server.region.asia', defaultMessage: 'Asia' }),
|
||||
australia: defineMessage({ id: 'project.server.region.australia', defaultMessage: 'Australia' }),
|
||||
south_america: defineMessage({
|
||||
id: 'project.server.region.south_america',
|
||||
defaultMessage: 'South America',
|
||||
}),
|
||||
middle_east: defineMessage({
|
||||
id: 'project.server.region.middle_east',
|
||||
defaultMessage: 'Middle East',
|
||||
}),
|
||||
russia: defineMessage({ id: 'project.server.region.russia', defaultMessage: 'Russia' }),
|
||||
}
|
||||
|
||||
export const SERVER_LANGUAGES = [
|
||||
{ code: 'en', name: 'English' },
|
||||
{ code: 'es', name: 'Spanish' },
|
||||
{ code: 'pt', name: 'Portuguese' },
|
||||
{ code: 'fr', name: 'French' },
|
||||
{ code: 'de', name: 'German' },
|
||||
{ code: 'it', name: 'Italian' },
|
||||
{ code: 'nl', name: 'Dutch' },
|
||||
{ code: 'ru', name: 'Russian' },
|
||||
{ code: 'uk', name: 'Ukrainian' },
|
||||
{ code: 'pl', name: 'Polish' },
|
||||
{ code: 'cs', name: 'Czech' },
|
||||
{ code: 'sk', name: 'Slovak' },
|
||||
{ code: 'hu', name: 'Hungarian' },
|
||||
{ code: 'ro', name: 'Romanian' },
|
||||
{ code: 'bg', name: 'Bulgarian' },
|
||||
{ code: 'hr', name: 'Croatian' },
|
||||
{ code: 'sr', name: 'Serbian' },
|
||||
{ code: 'el', name: 'Greek' },
|
||||
{ code: 'tr', name: 'Turkish' },
|
||||
{ code: 'ar', name: 'Arabic' },
|
||||
{ code: 'he', name: 'Hebrew' },
|
||||
{ code: 'hi', name: 'Hindi' },
|
||||
{ code: 'bn', name: 'Bengali' },
|
||||
{ code: 'ur', name: 'Urdu' },
|
||||
{ code: 'zh', name: 'Chinese' },
|
||||
{ code: 'ja', name: 'Japanese' },
|
||||
{ code: 'ko', name: 'Korean' },
|
||||
{ code: 'th', name: 'Thai' },
|
||||
{ code: 'vi', name: 'Vietnamese' },
|
||||
{ code: 'id', name: 'Indonesian' },
|
||||
{ code: 'ms', name: 'Malay' },
|
||||
{ code: 'tl', name: 'Filipino' },
|
||||
{ code: 'sv', name: 'Swedish' },
|
||||
{ code: 'no', name: 'Norwegian' },
|
||||
{ code: 'da', name: 'Danish' },
|
||||
{ code: 'fi', name: 'Finnish' },
|
||||
{ code: 'lt', name: 'Lithuanian' },
|
||||
{ code: 'lv', name: 'Latvian' },
|
||||
{ code: 'et', name: 'Estonian' },
|
||||
{ code: 'af', name: 'Afrikaans' },
|
||||
{ code: 'am', name: 'Amharic' },
|
||||
{ code: 'az', name: 'Azerbaijani' },
|
||||
{ code: 'be', name: 'Belarusian' },
|
||||
{ code: 'bs', name: 'Bosnian' },
|
||||
{ code: 'ca', name: 'Catalan' },
|
||||
{ code: 'eo', name: 'Esperanto' },
|
||||
{ code: 'eu', name: 'Basque' },
|
||||
{ code: 'fa', name: 'Persian' },
|
||||
{ code: 'ga', name: 'Irish' },
|
||||
{ code: 'gl', name: 'Galician' },
|
||||
{ code: 'hy', name: 'Armenian' },
|
||||
{ code: 'is', name: 'Icelandic' },
|
||||
{ code: 'ka', name: 'Georgian' },
|
||||
{ code: 'kk', name: 'Kazakh' },
|
||||
{ code: 'km', name: 'Khmer' },
|
||||
{ code: 'kn', name: 'Kannada' },
|
||||
{ code: 'lo', name: 'Lao' },
|
||||
{ code: 'mk', name: 'Macedonian' },
|
||||
{ code: 'ml', name: 'Malayalam' },
|
||||
{ code: 'mn', name: 'Mongolian' },
|
||||
{ code: 'mr', name: 'Marathi' },
|
||||
{ code: 'my', name: 'Burmese' },
|
||||
{ code: 'ne', name: 'Nepali' },
|
||||
{ code: 'pa', name: 'Punjabi' },
|
||||
{ code: 'si', name: 'Sinhala' },
|
||||
{ code: 'sl', name: 'Slovenian' },
|
||||
{ code: 'sq', name: 'Albanian' },
|
||||
{ code: 'sw', name: 'Swahili' },
|
||||
{ code: 'ta', name: 'Tamil' },
|
||||
{ code: 'te', name: 'Telugu' },
|
||||
{ code: 'uz', name: 'Uzbek' },
|
||||
{ code: 'yo', name: 'Yoruba' },
|
||||
{ code: 'zu', name: 'Zulu' },
|
||||
]
|
||||
export const SERVER_LANGUAGES = {
|
||||
en: defineMessage({ id: 'project.server.language.en', defaultMessage: 'English' }),
|
||||
es: defineMessage({ id: 'project.server.language.es', defaultMessage: 'Spanish' }),
|
||||
pt: defineMessage({ id: 'project.server.language.pt', defaultMessage: 'Portuguese' }),
|
||||
fr: defineMessage({ id: 'project.server.language.fr', defaultMessage: 'French' }),
|
||||
de: defineMessage({ id: 'project.server.language.de', defaultMessage: 'German' }),
|
||||
it: defineMessage({ id: 'project.server.language.it', defaultMessage: 'Italian' }),
|
||||
nl: defineMessage({ id: 'project.server.language.nl', defaultMessage: 'Dutch' }),
|
||||
ru: defineMessage({ id: 'project.server.language.ru', defaultMessage: 'Russian' }),
|
||||
uk: defineMessage({ id: 'project.server.language.uk', defaultMessage: 'Ukrainian' }),
|
||||
pl: defineMessage({ id: 'project.server.language.pl', defaultMessage: 'Polish' }),
|
||||
cs: defineMessage({ id: 'project.server.language.cs', defaultMessage: 'Czech' }),
|
||||
sk: defineMessage({ id: 'project.server.language.sk', defaultMessage: 'Slovak' }),
|
||||
hu: defineMessage({ id: 'project.server.language.hu', defaultMessage: 'Hungarian' }),
|
||||
ro: defineMessage({ id: 'project.server.language.ro', defaultMessage: 'Romanian' }),
|
||||
bg: defineMessage({ id: 'project.server.language.bg', defaultMessage: 'Bulgarian' }),
|
||||
hr: defineMessage({ id: 'project.server.language.hr', defaultMessage: 'Croatian' }),
|
||||
sr: defineMessage({ id: 'project.server.language.sr', defaultMessage: 'Serbian' }),
|
||||
el: defineMessage({ id: 'project.server.language.el', defaultMessage: 'Greek' }),
|
||||
tr: defineMessage({ id: 'project.server.language.tr', defaultMessage: 'Turkish' }),
|
||||
ar: defineMessage({ id: 'project.server.language.ar', defaultMessage: 'Arabic' }),
|
||||
he: defineMessage({ id: 'project.server.language.he', defaultMessage: 'Hebrew' }),
|
||||
hi: defineMessage({ id: 'project.server.language.hi', defaultMessage: 'Hindi' }),
|
||||
bn: defineMessage({ id: 'project.server.language.bn', defaultMessage: 'Bengali' }),
|
||||
ur: defineMessage({ id: 'project.server.language.ur', defaultMessage: 'Urdu' }),
|
||||
zh: defineMessage({ id: 'project.server.language.zh', defaultMessage: 'Chinese' }),
|
||||
ja: defineMessage({ id: 'project.server.language.ja', defaultMessage: 'Japanese' }),
|
||||
ko: defineMessage({ id: 'project.server.language.ko', defaultMessage: 'Korean' }),
|
||||
th: defineMessage({ id: 'project.server.language.th', defaultMessage: 'Thai' }),
|
||||
vi: defineMessage({ id: 'project.server.language.vi', defaultMessage: 'Vietnamese' }),
|
||||
id: defineMessage({ id: 'project.server.language.id', defaultMessage: 'Indonesian' }),
|
||||
ms: defineMessage({ id: 'project.server.language.ms', defaultMessage: 'Malay' }),
|
||||
tl: defineMessage({ id: 'project.server.language.tl', defaultMessage: 'Filipino' }),
|
||||
sv: defineMessage({ id: 'project.server.language.sv', defaultMessage: 'Swedish' }),
|
||||
no: defineMessage({ id: 'project.server.language.no', defaultMessage: 'Norwegian' }),
|
||||
da: defineMessage({ id: 'project.server.language.da', defaultMessage: 'Danish' }),
|
||||
fi: defineMessage({ id: 'project.server.language.fi', defaultMessage: 'Finnish' }),
|
||||
lt: defineMessage({ id: 'project.server.language.lt', defaultMessage: 'Lithuanian' }),
|
||||
lv: defineMessage({ id: 'project.server.language.lv', defaultMessage: 'Latvian' }),
|
||||
et: defineMessage({ id: 'project.server.language.et', defaultMessage: 'Estonian' }),
|
||||
af: defineMessage({ id: 'project.server.language.af', defaultMessage: 'Afrikaans' }),
|
||||
am: defineMessage({ id: 'project.server.language.am', defaultMessage: 'Amharic' }),
|
||||
az: defineMessage({ id: 'project.server.language.az', defaultMessage: 'Azerbaijani' }),
|
||||
be: defineMessage({ id: 'project.server.language.be', defaultMessage: 'Belarusian' }),
|
||||
bs: defineMessage({ id: 'project.server.language.bs', defaultMessage: 'Bosnian' }),
|
||||
ca: defineMessage({ id: 'project.server.language.ca', defaultMessage: 'Catalan' }),
|
||||
eo: defineMessage({ id: 'project.server.language.eo', defaultMessage: 'Esperanto' }),
|
||||
eu: defineMessage({ id: 'project.server.language.eu', defaultMessage: 'Basque' }),
|
||||
fa: defineMessage({ id: 'project.server.language.fa', defaultMessage: 'Persian' }),
|
||||
ga: defineMessage({ id: 'project.server.language.ga', defaultMessage: 'Irish' }),
|
||||
gl: defineMessage({ id: 'project.server.language.gl', defaultMessage: 'Galician' }),
|
||||
hy: defineMessage({ id: 'project.server.language.hy', defaultMessage: 'Armenian' }),
|
||||
is: defineMessage({ id: 'project.server.language.is', defaultMessage: 'Icelandic' }),
|
||||
ka: defineMessage({ id: 'project.server.language.ka', defaultMessage: 'Georgian' }),
|
||||
kk: defineMessage({ id: 'project.server.language.kk', defaultMessage: 'Kazakh' }),
|
||||
km: defineMessage({ id: 'project.server.language.km', defaultMessage: 'Khmer' }),
|
||||
kn: defineMessage({ id: 'project.server.language.kn', defaultMessage: 'Kannada' }),
|
||||
lo: defineMessage({ id: 'project.server.language.lo', defaultMessage: 'Lao' }),
|
||||
mk: defineMessage({ id: 'project.server.language.mk', defaultMessage: 'Macedonian' }),
|
||||
ml: defineMessage({ id: 'project.server.language.ml', defaultMessage: 'Malayalam' }),
|
||||
mn: defineMessage({ id: 'project.server.language.mn', defaultMessage: 'Mongolian' }),
|
||||
mr: defineMessage({ id: 'project.server.language.mr', defaultMessage: 'Marathi' }),
|
||||
my: defineMessage({ id: 'project.server.language.my', defaultMessage: 'Burmese' }),
|
||||
ne: defineMessage({ id: 'project.server.language.ne', defaultMessage: 'Nepali' }),
|
||||
pa: defineMessage({ id: 'project.server.language.pa', defaultMessage: 'Punjabi' }),
|
||||
si: defineMessage({ id: 'project.server.language.si', defaultMessage: 'Sinhala' }),
|
||||
sl: defineMessage({ id: 'project.server.language.sl', defaultMessage: 'Slovenian' }),
|
||||
sq: defineMessage({ id: 'project.server.language.sq', defaultMessage: 'Albanian' }),
|
||||
sw: defineMessage({ id: 'project.server.language.sw', defaultMessage: 'Swahili' }),
|
||||
ta: defineMessage({ id: 'project.server.language.ta', defaultMessage: 'Tamil' }),
|
||||
te: defineMessage({ id: 'project.server.language.te', defaultMessage: 'Telugu' }),
|
||||
uz: defineMessage({ id: 'project.server.language.uz', defaultMessage: 'Uzbek' }),
|
||||
yo: defineMessage({ id: 'project.server.language.yo', defaultMessage: 'Yoruba' }),
|
||||
zu: defineMessage({ id: 'project.server.language.zu', defaultMessage: 'Zulu' }),
|
||||
}
|
||||
|
||||
export const SERVER_SORT_TYPES: SortType[] = [
|
||||
{ display: 'Relevance', name: 'relevance' },
|
||||
@@ -123,7 +131,10 @@ export function useServerSearch(opts: {
|
||||
}) {
|
||||
const { tags, query, maxResults, currentPage } = opts
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const { formatMessage, locale } = useVIntl()
|
||||
const formatCategoryName = (categoryName: string) => {
|
||||
return formatCategory(formatMessage, categoryName)
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
@@ -133,8 +144,8 @@ export function useServerSearch(opts: {
|
||||
|
||||
const serverFilterTypes = computed<FilterType[]>(() => {
|
||||
const categoryFilters: Record<string, FilterType> = {}
|
||||
for (const c of (tags.value?.categories ?? []).filter(
|
||||
(c) => c.project_type === 'minecraft_java_server',
|
||||
for (const c of sortedCategories(tags.value, formatCategoryName, locale.value).filter(
|
||||
(c: Labrinth.Tags.v2.Category) => c.project_type === 'minecraft_java_server',
|
||||
)) {
|
||||
const filterTypeId = `server_category_${c.header}`
|
||||
if (!categoryFilters[filterTypeId]) {
|
||||
@@ -158,27 +169,64 @@ export function useServerSearch(opts: {
|
||||
})
|
||||
}
|
||||
|
||||
const featuresFilter = categoryFilters['server_category_minecraft_server_features']
|
||||
if (featuresFilter) {
|
||||
featuresFilter.options.sort((a, b) => {
|
||||
if (a.id === 'pokemon') return -1
|
||||
if (b.id === 'pokemon') return 1
|
||||
return 0
|
||||
})
|
||||
}
|
||||
const sortedRegions = Object.entries(SERVER_REGIONS).sort(([_, a], [__, b]) => {
|
||||
const aFormatted = formatMessage(a)
|
||||
const bFormatted = formatMessage(b)
|
||||
return aFormatted.localeCompare(bFormatted, locale.value)
|
||||
})
|
||||
|
||||
const localeDefinition = LOCALES.find((l) => l.code === locale.value)
|
||||
const userLanguageCode =
|
||||
localeDefinition?.serverLanguageCode ?? locale.value.substring(0, locale.value.indexOf('-'))
|
||||
const sortedLanguages = Object.entries(SERVER_LANGUAGES).sort(([aCode, a], [bCode, b]) => {
|
||||
if (aCode === 'en') return -1
|
||||
if (bCode === 'en') return 1
|
||||
|
||||
if (aCode === userLanguageCode) return -1
|
||||
if (bCode === userLanguageCode) return 1
|
||||
|
||||
const aFormatted = formatMessage(a)
|
||||
const bFormatted = formatMessage(b)
|
||||
return aFormatted.localeCompare(bFormatted, locale.value)
|
||||
})
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'server_content_type',
|
||||
formatted_name: 'Type',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.filter_type.server_content_type',
|
||||
defaultMessage: 'Type',
|
||||
}),
|
||||
),
|
||||
supported_project_types: ['server'],
|
||||
display: 'all',
|
||||
query_param: 'sct',
|
||||
supports_negative_filter: false,
|
||||
searchable: false,
|
||||
options: [
|
||||
{ id: 'vanilla', formatted_name: 'Vanilla', method: 'or', value: 'vanilla' },
|
||||
{ id: 'modpack', formatted_name: 'Modded', method: 'or', value: 'modpack' },
|
||||
{
|
||||
id: 'vanilla',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.server_content_type.vanilla',
|
||||
defaultMessage: 'Vanilla',
|
||||
}),
|
||||
),
|
||||
method: 'or',
|
||||
value: 'vanilla',
|
||||
},
|
||||
{
|
||||
id: 'modpack',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.server_content_type.modpack',
|
||||
defaultMessage: 'Modded',
|
||||
}),
|
||||
),
|
||||
method: 'or',
|
||||
value: 'modpack',
|
||||
},
|
||||
],
|
||||
},
|
||||
...[
|
||||
@@ -191,7 +239,12 @@ export function useServerSearch(opts: {
|
||||
.filter(Boolean),
|
||||
{
|
||||
id: 'server_game_version',
|
||||
formatted_name: 'Game Version',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.filter_type.game_version',
|
||||
defaultMessage: 'Game version',
|
||||
}),
|
||||
),
|
||||
supported_project_types: ['server'],
|
||||
display: 'scrollable',
|
||||
query_param: 'sgv',
|
||||
@@ -207,45 +260,81 @@ export function useServerSearch(opts: {
|
||||
},
|
||||
{
|
||||
id: 'server_region',
|
||||
formatted_name: 'Region',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.filter_type.server_region',
|
||||
defaultMessage: 'Region',
|
||||
}),
|
||||
),
|
||||
supported_project_types: ['server'],
|
||||
display: 'all',
|
||||
query_param: 'sr',
|
||||
supports_negative_filter: true,
|
||||
searchable: false,
|
||||
options: SERVER_REGIONS.map((r) => ({
|
||||
id: r.code,
|
||||
formatted_name: r.name,
|
||||
options: sortedRegions.map(([code, name]) => ({
|
||||
id: code,
|
||||
formatted_name: formatMessage(name),
|
||||
method: 'or' as const,
|
||||
value: r.code,
|
||||
value: code,
|
||||
})),
|
||||
},
|
||||
{
|
||||
id: 'server_language',
|
||||
formatted_name: 'Language',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.filter_type.server_language',
|
||||
defaultMessage: 'Language',
|
||||
}),
|
||||
),
|
||||
supported_project_types: ['server'],
|
||||
display: 'scrollable',
|
||||
query_param: 'sl',
|
||||
supports_negative_filter: false,
|
||||
searchable: true,
|
||||
options: SERVER_LANGUAGES.map((l) => ({
|
||||
id: l.code,
|
||||
formatted_name: l.name,
|
||||
options: sortedLanguages.map(([code, name]) => ({
|
||||
id: code,
|
||||
formatted_name: formatMessage(name),
|
||||
icon: code === 'en' ? GlobeIcon : code === userLanguageCode ? UserIcon : undefined,
|
||||
method: 'or' as const,
|
||||
value: l.code,
|
||||
value: code,
|
||||
})),
|
||||
},
|
||||
{
|
||||
id: 'server_status',
|
||||
formatted_name: 'Status',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'search.filter_type.server_status',
|
||||
defaultMessage: 'Status',
|
||||
}),
|
||||
),
|
||||
supported_project_types: ['server'],
|
||||
display: 'all',
|
||||
query_param: 'sst',
|
||||
supports_negative_filter: false,
|
||||
searchable: false,
|
||||
options: [
|
||||
{ id: 'online', formatted_name: 'Online', method: 'or', value: 'online' },
|
||||
{ id: 'offline', formatted_name: 'Offline', method: 'or', value: 'offline' },
|
||||
{
|
||||
id: 'online',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'project.server.status.online',
|
||||
defaultMessage: 'Online',
|
||||
}),
|
||||
),
|
||||
method: 'or',
|
||||
value: 'online',
|
||||
},
|
||||
{
|
||||
id: 'offline',
|
||||
formatted_name: formatMessage(
|
||||
defineMessage({
|
||||
id: 'project.server.status.offline',
|
||||
defaultMessage: 'Offline',
|
||||
}),
|
||||
),
|
||||
method: 'or',
|
||||
value: 'offline',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
@@ -324,7 +324,7 @@ export const categoryMessages = defineMessages({
|
||||
},
|
||||
kitpvp: {
|
||||
id: 'tag.category.kitpvp',
|
||||
defaultMessage: 'Kit PVP',
|
||||
defaultMessage: 'Kit PvP',
|
||||
},
|
||||
library: {
|
||||
id: 'tag.category.library',
|
||||
@@ -436,7 +436,7 @@ export const categoryMessages = defineMessages({
|
||||
},
|
||||
pokemon: {
|
||||
id: 'tag.category.pokemon',
|
||||
defaultMessage: 'Pokemon',
|
||||
defaultMessage: 'Pokémon',
|
||||
},
|
||||
potato: {
|
||||
id: 'tag.category.potato',
|
||||
@@ -448,11 +448,11 @@ export const categoryMessages = defineMessages({
|
||||
},
|
||||
pve: {
|
||||
id: 'tag.category.pve',
|
||||
defaultMessage: 'PVE',
|
||||
defaultMessage: 'PvE',
|
||||
},
|
||||
pvp: {
|
||||
id: 'tag.category.pvp',
|
||||
defaultMessage: 'PVP',
|
||||
defaultMessage: 'PvP',
|
||||
},
|
||||
questing: {
|
||||
id: 'tag.category.questing',
|
||||
|
||||
Reference in New Issue
Block a user