1
0

Make home page translatable, fix scrolling content animation timing (#4325)

* Make home page translatable, fix scrolling content animation timing

* intl:extract
This commit is contained in:
Prospector
2025-09-02 09:03:39 -07:00
committed by GitHub
parent bd3342badf
commit c1a092e55c
5 changed files with 479 additions and 95 deletions

View File

@@ -1,7 +1,9 @@
<template>
<div class="mx-2 p-4 !py-8 sm:mx-8 sm:p-32">
<div class="my-8 flex items-center justify-between">
<h2 class="m-0 mx-auto text-3xl font-extrabold sm:text-4xl">Latest news from Modrinth</h2>
<h2 class="m-0 mx-auto text-3xl font-extrabold sm:text-4xl">
{{ formatMessage(messages.latestNews) }}
</h2>
</div>
<div v-if="latestArticles" class="grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-4">
@@ -17,7 +19,7 @@
<ButtonStyled color="brand" size="large">
<nuxt-link to="/news">
<NewspaperIcon />
View all news
{{ formatMessage(messages.viewAll) }}
</nuxt-link>
</ButtonStyled>
</div>
@@ -28,8 +30,11 @@
import { NewspaperIcon } from '@modrinth/assets'
import { articles as rawArticles } from '@modrinth/blog'
import { ButtonStyled, NewsArticleCard } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { computed, ref } from 'vue'
const { formatMessage } = useVIntl()
const articles = ref(
rawArticles
.map((article) => ({
@@ -45,5 +50,16 @@ const articles = ref(
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()),
)
const messages = defineMessages({
latestNews: {
id: 'ui.latest-news-row.latest-news',
defaultMessage: 'Latest news from Modrinth',
},
viewAll: {
id: 'ui.latest-news-row.view-all',
defaultMessage: 'View all news',
},
})
const latestArticles = computed(() => articles.value.slice(0, 3))
</script>

View File

@@ -332,6 +332,147 @@
"frog.title": {
"message": "Frog"
},
"landing.button.discover-mods": {
"message": "Discover mods"
},
"landing.button.go-to-dashboard": {
"message": "Go to dashboard"
},
"landing.creator.feature.constantly-evolving.description": {
"message": "Get the best modding experience possible with constant updates from the Modrinth team"
},
"landing.creator.feature.constantly-evolving.title": {
"message": "Constantly Evolving"
},
"landing.creator.feature.data-statistics.description": {
"message": "Get detailed reports on page views, download counts, and revenue"
},
"landing.creator.feature.data-statistics.title": {
"message": "Data and Statistics"
},
"landing.creator.feature.discovery.description": {
"message": "Get your project discovered by thousands of users through search, our home page, Discord server, and more ways to come in the future!"
},
"landing.creator.feature.discovery.title": {
"message": "Discovery"
},
"landing.creator.feature.diverse-ecosystem.description": {
"message": "Integrate with your build tools through Minotaur for automatic uploads right when you release a new version"
},
"landing.creator.feature.diverse-ecosystem.title": {
"message": "Diverse Ecosystem"
},
"landing.creator.feature.monetization.description": {
"message": "Get paid ad revenue from your project pages and withdraw your funds at any time"
},
"landing.creator.feature.monetization.title": {
"message": "Monetization"
},
"landing.creator.feature.team-management.description": {
"message": "Invite your teammates and manage roles and permissions with ease"
},
"landing.creator.feature.team-management.title": {
"message": "Team Management"
},
"landing.error.failedToLoadRandomProjects": {
"message": "Failed to load random projects :("
},
"landing.feature.follow.description": {
"message": "Get notified every time your favorite projects update and stay in the loop"
},
"landing.feature.follow.heading": {
"message": "Follow projects you love"
},
"landing.feature.launcher.description": {
"message": "Modrinth's open-source API lets launchers add deep integration with Modrinth. You can use Modrinth through <link>our own app</link> and some of the most popular launchers like ATLauncher, MultiMC, and Prism Launcher."
},
"landing.feature.launcher.heading": {
"message": "Play with your favorite launcher"
},
"landing.feature.search.description": {
"message": "Modrinth's lightning-fast search and powerful filters let you find what you want as you type."
},
"landing.feature.search.heading": {
"message": "Find what you want, quickly and easily"
},
"landing.heading.the-place-for-minecraft": {
"message": "The place for Minecraft <content></content>"
},
"landing.heading.the-place-for-minecraft.data-packs": {
"message": "data packs"
},
"landing.heading.the-place-for-minecraft.modpacks": {
"message": "modpacks"
},
"landing.heading.the-place-for-minecraft.mods": {
"message": "mods"
},
"landing.heading.the-place-for-minecraft.plugins": {
"message": "plugins"
},
"landing.heading.the-place-for-minecraft.resource-packs": {
"message": "resource packs"
},
"landing.heading.the-place-for-minecraft.servers": {
"message": "servers"
},
"landing.heading.the-place-for-minecraft.shaders": {
"message": "shaders"
},
"landing.launcher.atlauncher-label": {
"message": "ATLauncher"
},
"landing.launcher.graphic-alt": {
"message": "A simplified representation of a Minecraft window, with the Mojang Studios logo in Modrinth green."
},
"landing.launcher.modrinth-app-label": {
"message": "Modrinth App"
},
"landing.launcher.prism-launcher-label": {
"message": "Prism Launcher"
},
"landing.notifications.has-been-updated": {
"message": "{title} has been updated!"
},
"landing.notifications.heading": {
"message": "Notifications"
},
"landing.notifications.received-time": {
"message": "Received {time}"
},
"landing.notifications.version-released": {
"message": "Version {version} has been released for {gameVersion}"
},
"landing.search.label": {
"message": "Search"
},
"landing.search.placeholder": {
"message": "Search..."
},
"landing.search.sort-by.label": {
"message": "Sort by"
},
"landing.section.for-creators.description": {
"message": "Give an online home to your creations and reach a massive audience of dedicated players"
},
"landing.section.for-creators.label": {
"message": "For Creators"
},
"landing.section.for-creators.tagline": {
"message": "Share your content with the world"
},
"landing.section.for-players.description": {
"message": "From magical biomes to cursed dungeons, you can be sure to find content to bring your gameplay to the next level."
},
"landing.section.for-players.label": {
"message": "For Players"
},
"landing.section.for-players.tagline": {
"message": "Discover over {count} creations"
},
"landing.subheading": {
"message": "Discover, play, and share Minecraft content through our open-source platform built for the community."
},
"layout.action.change-theme": {
"message": "Change theme"
},
@@ -1675,5 +1816,11 @@
},
"settings.sessions.unknown-platform": {
"message": "Unknown platform"
},
"ui.latest-news-row.latest-news": {
"message": "Latest news from Modrinth"
},
"ui.latest-news-row.view-all": {
"message": "View all news"
}
}

View File

@@ -3,40 +3,43 @@
<div class="landing-hero">
<ModrinthIcon class="modrinth-icon text-brand" />
<h1 class="main-header">
The place for Minecraft
<div class="animate-strong">
<span>
<strong
v-for="projectType in tags.projectTypes"
:key="projectType.id"
class="main-header-strong"
>
{{ projectType.display }}s <br />
</strong>
<strong class="main-header-strong">servers <br /></strong>
<strong class="main-header-strong">mods</strong>
</span>
</div>
<IntlFormatted :message-id="messages.thePlaceForMinecraft">
<template #content>
<div class="animate-strong">
<span>
<strong
v-for="[key, message] in Object.entries(contentTypeMessages)"
:key="`landing-content-type-${key}`"
class="main-header-strong"
>
{{ formatMessage(message) }} <br />
</strong>
<strong class="main-header-strong">
{{ formatMessage(contentTypeMessages.mods) }}
</strong>
</span>
</div>
</template>
</IntlFormatted>
</h1>
<h2>
Discover, play, and share Minecraft content through our open-source platform built for the
community.
{{ formatMessage(messages.discoverHeading) }}
</h2>
<div class="button-group">
<ButtonStyled color="brand" size="large">
<nuxt-link to="/mods">
<CompassIcon aria-hidden="true" />
Discover mods
{{ formatMessage(messages.discoverMods) }}
</nuxt-link>
</ButtonStyled>
<ButtonStyled size="large" type="outlined">
<nuxt-link v-if="!auth.user" to="/auth/sign-up" rel="noopener nofollow">
<LogInIcon aria-hidden="true" />
Sign up
{{ formatMessage(commonMessages.signUpButton) }}
</nuxt-link>
<nuxt-link v-else to="/dashboard/projects">
<DashboardIcon aria-hidden="true" />
Go to dashboard
{{ formatMessage(messages.goToDashboard) }}
</nuxt-link>
</ButtonStyled>
</div>
@@ -65,44 +68,46 @@
</div>
</div>
<div v-else class="relative z-[10] w-full text-center text-xl font-bold text-contrast">
Failed to load random projects :(
{{ formatMessage(messages.failedToLoadRandomProjects) }}
</div>
<div class="projects-transition" />
<div class="users-section">
<div class="section-header">
<div class="section-label green">For Players</div>
<h2 class="section-tagline">Discover over 50,000 creations</h2>
<div class="section-label green">{{ formatMessage(messages.forPlayersLabel) }}</div>
<h2 class="section-tagline">
{{ formatMessage(messages.discoverCreationsTagline, { count: formattedProjectCount }) }}
</h2>
<p class="section-description">
From magical biomes to cursed dungeons, you can be sure to find content to bring your
gameplay to the next level.
{{ formatMessage(messages.playersDescription) }}
</p>
</div>
<div class="feature-blob">
<div class="blob-text">
<h3>Find what you want, quickly and easily</h3>
<h3>{{ formatMessage(messages.findWhatYouWantHeading) }}</h3>
<p>
Modrinth's lightning-fast search and powerful filters let you find what you want as
you type.
{{ formatMessage(messages.findWhatYouWantDescription) }}
</p>
</div>
<div class="blob-demonstration gradient-border bigger">
<div class="demo-search">
<div class="search-controls">
<div class="iconified-input">
<label class="hidden" for="search">Search</label>
<label class="hidden" for="search">{{
formatMessage(messages.searchLabel)
}}</label>
<SearchIcon aria-hidden="true" />
<input
id="search"
v-model="searchQuery"
type="search"
name="search"
:placeholder="`Search...`"
:placeholder="formatMessage(messages.searchPlaceholder)"
autocomplete="off"
@input="updateSearchProjects"
/>
</div>
<div class="sort-by">
<span class="label">Sort by</span>
<span class="label">{{ formatMessage(messages.sortByLabel) }}</span>
<Multiselect
v-model="sortType"
placeholder="Select one"
@@ -145,12 +150,12 @@
</div>
<div class="feature-blob reverse">
<div class="blob-text">
<h3>Follow projects you love</h3>
<p>Get notified every time your favorite projects update and stay in the loop</p>
<h3>{{ formatMessage(messages.followProjectsHeading) }}</h3>
<p>{{ formatMessage(messages.followProjectsDescription) }}</p>
</div>
<div class="blob-demonstration gradient-border">
<div class="notifs-demo">
<h3>Notifications</h3>
<h3>{{ formatMessage(messages.notificationsHeading) }}</h3>
<div class="notifications">
<div
v-for="(notification, index) in notifications"
@@ -168,24 +173,24 @@
:to="`${notification.project_type}/${notification.slug}`"
class="notif-header"
>
{{ notification.title }} has been updated!
{{ formatMessage(messages.hasBeenUpdated, { title: notification.title }) }}
</nuxt-link>
<p class="notif-desc">
Version {{ ['1.1.2', '1.0.3', '15.1'][index] }} has been released for
{{
$capitalizeString(
notification.display_categories[
notification.display_categories.length - 1
],
)
formatMessage(messages.versionReleased, {
version: ['1.1.2', '1.0.3', '15.1'][index],
gameVersion: notification.versions[notification.versions.length - 1],
})
}}
{{ notification.versions[notification.versions.length - 1] }}
</p>
<div class="date">
<CalendarIcon aria-hidden="true" />
<span>
Received
{{ formatRelativeTime(notification.date_modified) }}
{{
formatMessage(messages.receivedTime, {
time: formatRelativeTime(notification.date_modified),
})
}}
</span>
</div>
</div>
@@ -196,12 +201,13 @@
</div>
<div class="feature-blob">
<div class="blob-text">
<h3>Play with your favorite launcher</h3>
<h3>{{ formatMessage(messages.playWithLauncherHeading) }}</h3>
<p>
Modrinth's open-source API lets launchers add deep integration with Modrinth. You can
use Modrinth through
<nuxt-link class="title-link" to="/app">our own app</nuxt-link>
and some of the most popular launchers like ATLauncher, MultiMC, and Prism Launcher.
<IntlFormatted :message-id="messages.playWithLauncherDescription">
<template #link>
<nuxt-link class="title-link" to="/app">our own app</nuxt-link>
</template>
</IntlFormatted>
</p>
</div>
<div class="blob-demonstration gradient-border">
@@ -209,13 +215,13 @@
<img
v-if="$theme.active === 'light'"
src="https://cdn.modrinth.com/landing-new/launcher-light.webp"
alt="launcher graphic"
:alt="formatMessage(messages.launcherGraphicAlt)"
class="minecraft-screen"
/>
<img
v-else
src="https://cdn.modrinth.com/landing-new/launcher.webp"
alt="launcher graphic"
:alt="formatMessage(messages.launcherGraphicAlt)"
class="minecraft-screen"
/>
<div class="launcher-graphics">
@@ -223,15 +229,15 @@
rel="noopener"
href="https://prismlauncher.org/"
class="graphic gradient-border"
title="Prism Launcher"
aria-label="Prism Launcher"
:title="formatMessage(messages.prismLauncherLabel)"
:aria-label="formatMessage(messages.prismLauncherLabel)"
>
<PrismLauncherLogo aria-hidden="true" />
</a>
<nuxt-link
to="/app"
class="graphic gradient-border text-brand"
aria-label="Modrinth App"
:aria-label="formatMessage(messages.modrinthAppLabel)"
>
<ModrinthIcon aria-hidden="true" />
</nuxt-link>
@@ -239,8 +245,8 @@
rel="noopener"
href="https://atlauncher.com/"
class="graphic gradient-border"
title="ATLauncher"
aria-label="ATLauncher"
:title="formatMessage(messages.atlauncherLabel)"
:aria-label="formatMessage(messages.atlauncherLabel)"
>
<ATLauncherLogo aria-hidden="true" />
</a>
@@ -252,10 +258,10 @@
</div>
<div class="creator-section">
<div class="section-header">
<div class="section-label blue">For Creators</div>
<h2 class="section-tagline">Share your content with the world</h2>
<div class="section-label blue">{{ formatMessage(messages.forCreatorsLabel) }}</div>
<h2 class="section-tagline">{{ formatMessage(messages.shareContentTagline) }}</h2>
<p class="section-description">
Give an online home to your creations and reach a massive audience of dedicated players
{{ formatMessage(messages.creatorsDescription) }}
</p>
</div>
<div class="features">
@@ -281,10 +287,9 @@
</defs>
</svg>
</div>
<h3>Discovery</h3>
<h3>{{ formatMessage(creatorFeatureMessages.discoveryTitle) }}</h3>
<p>
Get your project discovered by thousands of users through search, our home page, Discord
server, and more ways to come in the future!
{{ formatMessage(creatorFeatureMessages.discoveryDescription) }}
</p>
</div>
<div class="feature gradient-border">
@@ -309,8 +314,8 @@
</defs>
</svg>
</div>
<h3>Team Management</h3>
<p>Invite your teammates and manage roles and permissions with ease</p>
<h3>{{ formatMessage(creatorFeatureMessages.teamManagementTitle) }}</h3>
<p>{{ formatMessage(creatorFeatureMessages.teamManagementDescription) }}</p>
</div>
<div class="feature gradient-border">
<div class="icon gradient-border">
@@ -334,8 +339,8 @@
</defs>
</svg>
</div>
<h3>Monetization</h3>
<p>Get paid ad revenue from your project pages and withdraw your funds at any time</p>
<h3>{{ formatMessage(creatorFeatureMessages.monetizationTitle) }}</h3>
<p>{{ formatMessage(creatorFeatureMessages.monetizationDescription) }}</p>
</div>
<div class="feature gradient-border">
<div class="icon gradient-border">
@@ -359,10 +364,9 @@
</defs>
</svg>
</div>
<h3>Diverse Ecosystem</h3>
<h3>{{ formatMessage(creatorFeatureMessages.diverseEcosystemTitle) }}</h3>
<p>
Integrate with your build tools through Minotaur for automatic uploads right when you
release a new version
{{ formatMessage(creatorFeatureMessages.diverseEcosystemDescription) }}
</p>
</div>
<div class="feature gradient-border">
@@ -387,8 +391,8 @@
</defs>
</svg>
</div>
<h3>Data and Statistics</h3>
<p>Get detailed reports on page views, download counts, and revenue</p>
<h3>{{ formatMessage(creatorFeatureMessages.dataStatisticsTitle) }}</h3>
<p>{{ formatMessage(creatorFeatureMessages.dataStatisticsDescription) }}</p>
</div>
<div class="feature gradient-border">
<div class="icon gradient-border">
@@ -412,9 +416,9 @@
</defs>
</svg>
</div>
<h3>Constantly Evolving</h3>
<h3>{{ formatMessage(creatorFeatureMessages.constantlyEvolvingTitle) }}</h3>
<p>
Get the best modding experience possible with constant updates from the Modrinth team
{{ formatMessage(creatorFeatureMessages.constantlyEvolvingDescription) }}
</p>
</div>
</div>
@@ -433,7 +437,9 @@ import {
ModrinthIcon,
SearchIcon,
} from '@modrinth/assets'
import { Avatar, ButtonStyled, useRelativeTime } from '@modrinth/ui'
import { Avatar, ButtonStyled, commonMessages, useRelativeTime } from '@modrinth/ui'
import { defineMessages, useVIntl } from '@vintl/vintl'
import { IntlFormatted } from '@vintl/vintl/components'
import { ref } from 'vue'
import { Multiselect } from 'vue-multiselect'
@@ -445,11 +451,16 @@ import { homePageNotifs, homePageProjects, homePageSearch } from '~/generated/st
const formatRelativeTime = useRelativeTime()
const { formatMessage } = useVIntl()
const searchQuery = ref('leave')
const sortType = ref('relevance')
const PROJECT_COUNT = 75000
const formatNumber = new Intl.NumberFormat().format
const formattedProjectCount = computed(() => formatNumber(PROJECT_COUNT))
const auth = await useAuth()
const tags = useTags()
const newProjects = homePageProjects?.slice(0, 40)
const val = Math.ceil(newProjects?.length / 3)
@@ -473,6 +484,213 @@ async function updateSearchProjects() {
searchProjects.value = res?.hits ?? []
}
const messages = defineMessages({
thePlaceForMinecraft: {
id: 'landing.heading.the-place-for-minecraft',
defaultMessage: 'The place for Minecraft <content></content>',
},
discoverHeading: {
id: 'landing.subheading',
defaultMessage:
'Discover, play, and share Minecraft content through our open-source platform built for the community.',
},
discoverMods: {
id: 'landing.button.discover-mods',
defaultMessage: 'Discover mods',
},
goToDashboard: {
id: 'landing.button.go-to-dashboard',
defaultMessage: 'Go to dashboard',
},
failedToLoadRandomProjects: {
id: 'landing.error.failedToLoadRandomProjects',
defaultMessage: 'Failed to load random projects :(',
},
forPlayersLabel: {
id: 'landing.section.for-players.label',
defaultMessage: 'For Players',
},
forCreatorsLabel: {
id: 'landing.section.for-creators.label',
defaultMessage: 'For Creators',
},
discoverCreationsTagline: {
id: 'landing.section.for-players.tagline',
defaultMessage: 'Discover over {count} creations',
},
shareContentTagline: {
id: 'landing.section.for-creators.tagline',
defaultMessage: 'Share your content with the world',
},
playersDescription: {
id: 'landing.section.for-players.description',
defaultMessage:
'From magical biomes to cursed dungeons, you can be sure to find content to bring your gameplay to the next level.',
},
creatorsDescription: {
id: 'landing.section.for-creators.description',
defaultMessage:
'Give an online home to your creations and reach a massive audience of dedicated players',
},
findWhatYouWantHeading: {
id: 'landing.feature.search.heading',
defaultMessage: 'Find what you want, quickly and easily',
},
findWhatYouWantDescription: {
id: 'landing.feature.search.description',
defaultMessage:
"Modrinth's lightning-fast search and powerful filters let you find what you want as you type.",
},
followProjectsHeading: {
id: 'landing.feature.follow.heading',
defaultMessage: 'Follow projects you love',
},
followProjectsDescription: {
id: 'landing.feature.follow.description',
defaultMessage: 'Get notified every time your favorite projects update and stay in the loop',
},
playWithLauncherHeading: {
id: 'landing.feature.launcher.heading',
defaultMessage: 'Play with your favorite launcher',
},
playWithLauncherDescription: {
id: 'landing.feature.launcher.description',
defaultMessage:
"Modrinth's open-source API lets launchers add deep integration with Modrinth. You can use Modrinth through <link>our own app</link> and some of the most popular launchers like ATLauncher, MultiMC, and Prism Launcher.",
},
searchPlaceholder: {
id: 'landing.search.placeholder',
defaultMessage: 'Search...',
},
searchLabel: {
id: 'landing.search.label',
defaultMessage: 'Search',
},
sortByLabel: {
id: 'landing.search.sort-by.label',
defaultMessage: 'Sort by',
},
notificationsHeading: {
id: 'landing.notifications.heading',
defaultMessage: 'Notifications',
},
hasBeenUpdated: {
id: 'landing.notifications.has-been-updated',
defaultMessage: '{title} has been updated!',
},
versionReleased: {
id: 'landing.notifications.version-released',
defaultMessage: 'Version {version} has been released for {gameVersion}',
},
receivedTime: {
id: 'landing.notifications.received-time',
defaultMessage: 'Received {time}',
},
launcherGraphicAlt: {
id: 'landing.launcher.graphic-alt',
defaultMessage:
'A simplified representation of a Minecraft window, with the Mojang Studios logo in Modrinth green.',
},
prismLauncherLabel: {
id: 'landing.launcher.prism-launcher-label',
defaultMessage: 'Prism Launcher',
},
modrinthAppLabel: {
id: 'landing.launcher.modrinth-app-label',
defaultMessage: 'Modrinth App',
},
atlauncherLabel: {
id: 'landing.launcher.atlauncher-label',
defaultMessage: 'ATLauncher',
},
})
const contentTypeMessages = defineMessages({
mods: {
id: 'landing.heading.the-place-for-minecraft.mods',
defaultMessage: 'mods',
},
resourcePacks: {
id: 'landing.heading.the-place-for-minecraft.resource-packs',
defaultMessage: 'resource packs',
},
dataPacks: {
id: 'landing.heading.the-place-for-minecraft.data-packs',
defaultMessage: 'data packs',
},
shaders: {
id: 'landing.heading.the-place-for-minecraft.shaders',
defaultMessage: 'shaders',
},
modpacks: {
id: 'landing.heading.the-place-for-minecraft.modpacks',
defaultMessage: 'modpacks',
},
plugins: {
id: 'landing.heading.the-place-for-minecraft.plugins',
defaultMessage: 'plugins',
},
servers: {
id: 'landing.heading.the-place-for-minecraft.servers',
defaultMessage: 'servers',
},
})
const creatorFeatureMessages = defineMessages({
discoveryTitle: {
id: 'landing.creator.feature.discovery.title',
defaultMessage: 'Discovery',
},
discoveryDescription: {
id: 'landing.creator.feature.discovery.description',
defaultMessage:
'Get your project discovered by thousands of users through search, our home page, Discord server, and more ways to come in the future!',
},
teamManagementTitle: {
id: 'landing.creator.feature.team-management.title',
defaultMessage: 'Team Management',
},
teamManagementDescription: {
id: 'landing.creator.feature.team-management.description',
defaultMessage: 'Invite your teammates and manage roles and permissions with ease',
},
monetizationTitle: {
id: 'landing.creator.feature.monetization.title',
defaultMessage: 'Monetization',
},
monetizationDescription: {
id: 'landing.creator.feature.monetization.description',
defaultMessage:
'Get paid ad revenue from your project pages and withdraw your funds at any time',
},
diverseEcosystemTitle: {
id: 'landing.creator.feature.diverse-ecosystem.title',
defaultMessage: 'Diverse Ecosystem',
},
diverseEcosystemDescription: {
id: 'landing.creator.feature.diverse-ecosystem.description',
defaultMessage:
'Integrate with your build tools through Minotaur for automatic uploads right when you release a new version',
},
dataStatisticsTitle: {
id: 'landing.creator.feature.data-statistics.title',
defaultMessage: 'Data and Statistics',
},
dataStatisticsDescription: {
id: 'landing.creator.feature.data-statistics.description',
defaultMessage: 'Get detailed reports on page views, download counts, and revenue',
},
constantlyEvolvingTitle: {
id: 'landing.creator.feature.constantly-evolving.title',
defaultMessage: 'Constantly Evolving',
},
constantlyEvolvingDescription: {
id: 'landing.creator.feature.constantly-evolving.description',
defaultMessage:
'Get the best modding experience possible with constant updates from the Modrinth team',
},
})
</script>
<style lang="scss" scoped>
@@ -1089,7 +1307,7 @@ async function updateSearchProjects() {
> span {
position: absolute;
top: 0;
animation: slide 12s infinite;
animation: slide 14s infinite;
@media (prefers-reduced-motion) {
animation-play-state: paused !important;
@@ -1098,40 +1316,36 @@ async function updateSearchProjects() {
@keyframes slide {
0%,
10% {
12.5% {
top: 0;
}
13%,
23% {
14.3%,
26.8% {
top: -1.2em;
}
26%,
36% {
28.6%,
41.1% {
top: -2.4em;
}
39%,
49% {
42.9%,
55.4% {
top: -3.6em;
}
52%,
62% {
57.2%,
69.7% {
top: -4.8em;
}
65%,
75% {
71.5%,
84% {
top: -6em;
}
78%,
88% {
85.8%,
98.3% {
top: -7.2em;
}
99.99997%,
99.99998% {
100% {
top: -8.4em;
}
99.99999% {
top: 0;
}
}
}

View File

@@ -77,6 +77,9 @@
"button.sign-out": {
"defaultMessage": "Sign out"
},
"button.sign-up": {
"defaultMessage": "Sign up"
},
"button.stop": {
"defaultMessage": "Stop"
},

View File

@@ -225,6 +225,10 @@ export const commonMessages = defineMessages({
id: 'button.sign-out',
defaultMessage: 'Sign out',
},
signUpButton: {
id: 'button.sign-up',
defaultMessage: 'Sign up',
},
singleplayerLabel: {
id: 'label.singleplayer',
defaultMessage: 'Singleplayer',