You've already forked AstralRinth
forked from didirus/AstralRinth
Add translations for the default page layout (#1616)
* Convert default.vue to composition API * Add translations to default page layout * Generate index.json * Fix sign up page * Generate index.json * Fix atUserLabel * Fix composition API port * Follow-up fixes for #1616 (#1618) * Re-organize default layout messages - Group some of the messages by their appearance (like banners) Grouping makes avoids having to think too much about the property names, keeps declarations clean, and also can be minified better, since variable names, unlike property names, can be easily mangled. - Remove needless type specification in property name[^1] It's already clear from where the message is formatted what it does, and if you need clarification, you can Ctrl+hover and see the type in the key. - Change some keys to conform to conventions We generally follow the pattern location > kind?. Things like 'label' are unnecessary, as everything is assumed to be label by default; the same applies to things like 'button', which are also often unnecessary as they're part of the location compound. - Remove message for handle, which should not be translatable It's very unlikely user handle format changes between any of the locales. [^1]: Common messages are pending restructuring that would fix this * Fix navRoutes not being computed in default layout * Fix untranslated Get Modrinth App buttons in default layout * Make legal disclaimer in the default layout translatable It wouldn't make much sense to leave it untranslated since it is meant for the end users too. It is also so small that it's unlikely to be mistranslated. * Extract missed legal disclaimer message from default layout * Make SEO strings in default layout translatable --------- Co-authored-by: Sasha Sorokin <10401817+brawaru@users.noreply.github.com>
This commit is contained in:
@@ -5,14 +5,16 @@
|
|||||||
class="email-nag"
|
class="email-nag"
|
||||||
>
|
>
|
||||||
<template v-if="auth.user.email">
|
<template v-if="auth.user.email">
|
||||||
<span>For security purposes, please verify your email address on Modrinth.</span>
|
<span>{{ formatMessage(verifyEmailBannerMessages.title) }}</span>
|
||||||
<button class="btn" @click="resendVerifyEmail">Re-send verification email</button>
|
<button class="btn" @click="resendVerifyEmail">
|
||||||
|
{{ formatMessage(verifyEmailBannerMessages.action) }}
|
||||||
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span>For security purposes, please enter your email on Modrinth.</span>
|
<span>{{ formatMessage(addEmailBannerMessages.title) }}</span>
|
||||||
<nuxt-link class="btn" to="/settings/account">
|
<nuxt-link class="btn" to="/settings/account">
|
||||||
<SettingsIcon />
|
<SettingsIcon />
|
||||||
Visit account settings
|
{{ formatMessage(addEmailBannerMessages.action) }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@@ -25,12 +27,10 @@
|
|||||||
>
|
>
|
||||||
<div class="site-banner__title">
|
<div class="site-banner__title">
|
||||||
<IssuesIcon />
|
<IssuesIcon />
|
||||||
<span> You’re viewing Modrinth’s staging environment </span>
|
<span>{{ formatMessage(stagingBannerMessages.title) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="site-banner__description">
|
<div class="site-banner__description">
|
||||||
The staging environment is running on a copy of the production Modrinth database. This is
|
{{ formatMessage(stagingBannerMessages.description) }}
|
||||||
used for testing and debugging purposes, and may be running in-development versions of the
|
|
||||||
Modrinth backend or frontend newer than the production instance.
|
|
||||||
</div>
|
</div>
|
||||||
<div class="site-banner__actions">
|
<div class="site-banner__actions">
|
||||||
<Button transparent icon-only :action="hideStagingBanner"><XIcon /></Button>
|
<Button transparent icon-only :action="hideStagingBanner"><XIcon /></Button>
|
||||||
@@ -53,13 +53,13 @@
|
|||||||
v-if="auth.user"
|
v-if="auth.user"
|
||||||
to="/dashboard/notifications"
|
to="/dashboard/notifications"
|
||||||
class="control-button button-transparent"
|
class="control-button button-transparent"
|
||||||
title="Notifications"
|
:title="formatMessage(commonMessages.notificationsLabel)"
|
||||||
>
|
>
|
||||||
<NotificationIcon aria-hidden="true" />
|
<NotificationIcon aria-hidden="true" />
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<button
|
<button
|
||||||
class="control-button button-transparent"
|
class="control-button button-transparent"
|
||||||
title="Switch theme"
|
:title="formatMessage(messages.changeTheme)"
|
||||||
@click="changeTheme"
|
@click="changeTheme"
|
||||||
>
|
>
|
||||||
<MoonIcon v-if="$colorMode.value === 'light'" aria-hidden="true" />
|
<MoonIcon v-if="$colorMode.value === 'light'" aria-hidden="true" />
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
<Avatar
|
<Avatar
|
||||||
:src="auth.user.avatar_url"
|
:src="auth.user.avatar_url"
|
||||||
class="user-icon"
|
class="user-icon"
|
||||||
alt="Your avatar"
|
:alt="formatMessage(messages.yourAvatarAlt)"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
circle
|
circle
|
||||||
/>
|
/>
|
||||||
@@ -88,13 +88,15 @@
|
|||||||
<NuxtLink class="item button-transparent" :to="`/user/${auth.user.username}`">
|
<NuxtLink class="item button-transparent" :to="`/user/${auth.user.username}`">
|
||||||
<div class="title profile-link">
|
<div class="title profile-link">
|
||||||
<div class="username">@{{ auth.user.username }}</div>
|
<div class="username">@{{ auth.user.username }}</div>
|
||||||
<div class="prompt">Visit your profile</div>
|
<div class="prompt">{{ formatMessage(messages.visitYourProfile) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
<button class="item button-transparent" @click="$refs.modal_creation.show()">
|
<button class="item button-transparent" @click="$refs.modal_creation.show()">
|
||||||
<PlusIcon class="icon" />
|
<PlusIcon class="icon" />
|
||||||
<span class="title">Create a project</span>
|
<span class="title">
|
||||||
|
{{ formatMessage(commonMessages.createAProjectButton) }}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
<NuxtLink class="item button-transparent" to="/dashboard/collections">
|
<NuxtLink class="item button-transparent" to="/dashboard/collections">
|
||||||
@@ -103,15 +105,17 @@
|
|||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink class="item button-transparent" to="/dashboard/notifications">
|
<NuxtLink class="item button-transparent" to="/dashboard/notifications">
|
||||||
<NotificationIcon class="icon" />
|
<NotificationIcon class="icon" />
|
||||||
<span class="title">Notifications</span>
|
<span class="title">{{
|
||||||
|
formatMessage(commonMessages.notificationsLabel)
|
||||||
|
}}</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink class="item button-transparent" to="/dashboard">
|
<NuxtLink class="item button-transparent" to="/dashboard">
|
||||||
<ChartIcon class="icon" />
|
<ChartIcon class="icon" />
|
||||||
<span class="title">Dashboard</span>
|
<span class="title">{{ formatMessage(commonMessages.dashboardLabel) }}</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink class="item button-transparent" to="/settings">
|
<NuxtLink class="item button-transparent" to="/settings">
|
||||||
<SettingsIcon class="icon" />
|
<SettingsIcon class="icon" />
|
||||||
<span class="title">Settings</span>
|
<span class="title">{{ formatMessage(commonMessages.settingsLabel) }}</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-if="tags.staffRoles.includes(auth.user.role)"
|
v-if="tags.staffRoles.includes(auth.user.role)"
|
||||||
@@ -119,7 +123,7 @@
|
|||||||
to="/moderation"
|
to="/moderation"
|
||||||
>
|
>
|
||||||
<ModerationIcon class="icon" />
|
<ModerationIcon class="icon" />
|
||||||
<span class="title">Moderation</span>
|
<span class="title">{{ formatMessage(commonMessages.moderationLabel) }}</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-if="!cosmetics.hideModrinthAppPromos"
|
v-if="!cosmetics.hideModrinthAppPromos"
|
||||||
@@ -127,25 +131,29 @@
|
|||||||
to="/app"
|
to="/app"
|
||||||
>
|
>
|
||||||
<DownloadIcon class="icon" />
|
<DownloadIcon class="icon" />
|
||||||
<span class="title">Get Modrinth App</span>
|
<span class="title">
|
||||||
|
{{ formatMessage(messages.getModrinthApp) }}
|
||||||
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<hr class="divider" />
|
<hr class="divider" />
|
||||||
<button class="item button-transparent" @click="logoutUser()">
|
<button class="item button-transparent" @click="logoutUser()">
|
||||||
<LogOutIcon class="icon" />
|
<LogOutIcon class="icon" />
|
||||||
<span class="dropdown-item__text">Log out</span>
|
<span class="dropdown-item__text">
|
||||||
|
{{ formatMessage(commonMessages.signOutButton) }}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<section v-else class="auth-prompt">
|
<section v-else class="auth-prompt">
|
||||||
<nuxt-link class="iconified-button raised-button" to="/auth/sign-in">
|
<nuxt-link class="iconified-button raised-button" to="/auth/sign-in">
|
||||||
<LogInIcon /> Sign in
|
<LogInIcon /> {{ formatMessage(commonMessages.signInButton) }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
v-if="$route.path !== '/app' && !cosmetics.hideModrinthAppPromos"
|
v-if="$route.path !== '/app' && !cosmetics.hideModrinthAppPromos"
|
||||||
class="btn btn-outline btn-primary app-btn"
|
class="btn btn-outline btn-primary app-btn"
|
||||||
to="/app"
|
to="/app"
|
||||||
>
|
>
|
||||||
<DownloadIcon /> Get Modrinth App
|
<DownloadIcon /> {{ formatMessage(messages.getModrinthApp) }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
@@ -185,32 +193,32 @@
|
|||||||
<Avatar
|
<Avatar
|
||||||
:src="auth.user.avatar_url"
|
:src="auth.user.avatar_url"
|
||||||
class="user-icon"
|
class="user-icon"
|
||||||
alt="Your avatar"
|
:alt="formatMessage(messages.yourAvatarAlt)"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
circle
|
circle
|
||||||
/>
|
/>
|
||||||
<div class="account-text">
|
<div class="account-text">
|
||||||
<div>@{{ auth.user.username }}</div>
|
<div>@{{ auth.user.username }}</div>
|
||||||
<div>Visit your profile</div>
|
<div>{{ formatMessage(messages.visitYourProfile) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<nuxt-link v-else class="iconified-button brand-button" to="/auth/sign-in">
|
<nuxt-link v-else class="iconified-button brand-button" to="/auth/sign-in">
|
||||||
<LogInIcon /> Sign in
|
<LogInIcon /> {{ formatMessage(commonMessages.signInButton) }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<template v-if="auth.user">
|
<template v-if="auth.user">
|
||||||
<button class="iconified-button danger-button" @click="logoutUser()">
|
<button class="iconified-button danger-button" @click="logoutUser()">
|
||||||
<LogOutIcon aria-hidden="true" />
|
<LogOutIcon aria-hidden="true" />
|
||||||
Log out
|
{{ formatMessage(commonMessages.signOutButton) }}
|
||||||
</button>
|
</button>
|
||||||
<button class="iconified-button" @click="$refs.modal_creation.show()">
|
<button class="iconified-button" @click="$refs.modal_creation.show()">
|
||||||
<PlusIcon aria-hidden="true" />
|
<PlusIcon aria-hidden="true" />
|
||||||
Create a project
|
{{ formatMessage(commonMessages.createAProjectButton) }}
|
||||||
</button>
|
</button>
|
||||||
<NuxtLink class="iconified-button" to="/dashboard/collections">
|
<NuxtLink class="iconified-button" to="/dashboard/collections">
|
||||||
<LibraryIcon class="icon" />
|
<LibraryIcon class="icon" />
|
||||||
Collections
|
{{ formatMessage(commonMessages.collectionsLabel) }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-if="auth.user.role === 'moderator' || auth.user.role === 'admin'"
|
v-if="auth.user.role === 'moderator' || auth.user.role === 'admin'"
|
||||||
@@ -218,28 +226,34 @@
|
|||||||
to="/moderation"
|
to="/moderation"
|
||||||
>
|
>
|
||||||
<ModerationIcon aria-hidden="true" />
|
<ModerationIcon aria-hidden="true" />
|
||||||
Moderation
|
{{ formatMessage(commonMessages.moderationLabel) }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
<NuxtLink class="iconified-button" to="/settings">
|
<NuxtLink class="iconified-button" to="/settings">
|
||||||
<SettingsIcon aria-hidden="true" />
|
<SettingsIcon aria-hidden="true" />
|
||||||
Settings
|
{{ formatMessage(commonMessages.settingsLabel) }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<button class="iconified-button" @click="changeTheme">
|
<button class="iconified-button" @click="changeTheme">
|
||||||
<MoonIcon v-if="$colorMode.value === 'light'" class="icon" />
|
<MoonIcon v-if="$colorMode.value === 'light'" class="icon" />
|
||||||
<SunIcon v-else class="icon" />
|
<SunIcon v-else class="icon" />
|
||||||
<span class="dropdown-item__text">Change theme</span>
|
<span class="dropdown-item__text">
|
||||||
|
{{ formatMessage(messages.changeTheme) }}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mobile-navbar" :class="{ expanded: isBrowseMenuOpen || isMobileMenuOpen }">
|
<div class="mobile-navbar" :class="{ expanded: isBrowseMenuOpen || isMobileMenuOpen }">
|
||||||
<NuxtLink to="/" class="tab button-animation" title="Home">
|
<NuxtLink
|
||||||
|
to="/"
|
||||||
|
class="tab button-animation"
|
||||||
|
:title="formatMessage(navMenuMessages.home)"
|
||||||
|
>
|
||||||
<HomeIcon />
|
<HomeIcon />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<button
|
<button
|
||||||
class="tab button-animation"
|
class="tab button-animation"
|
||||||
:class="{ 'router-link-exact-active': isBrowseMenuOpen }"
|
:class="{ 'router-link-exact-active': isBrowseMenuOpen }"
|
||||||
title="Search"
|
:title="formatMessage(navMenuMessages.search)"
|
||||||
@click="toggleBrowseMenu()"
|
@click="toggleBrowseMenu()"
|
||||||
>
|
>
|
||||||
<template v-if="auth.user">
|
<template v-if="auth.user">
|
||||||
@@ -247,7 +261,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<SearchIcon class="smaller" />
|
<SearchIcon class="smaller" />
|
||||||
Search
|
{{ formatMessage(navMenuMessages.search) }}
|
||||||
</template>
|
</template>
|
||||||
</button>
|
</button>
|
||||||
<template v-if="auth.user">
|
<template v-if="auth.user">
|
||||||
@@ -257,7 +271,7 @@
|
|||||||
:class="{
|
:class="{
|
||||||
'no-active': isMobileMenuOpen || isBrowseMenuOpen,
|
'no-active': isMobileMenuOpen || isBrowseMenuOpen,
|
||||||
}"
|
}"
|
||||||
title="Notifications"
|
:title="formatMessage(commonMessages.notificationsLabel)"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
isMobileMenuOpen = false
|
isMobileMenuOpen = false
|
||||||
@@ -267,13 +281,17 @@
|
|||||||
>
|
>
|
||||||
<NotificationIcon />
|
<NotificationIcon />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink to="/dashboard" class="tab button-animation" title="Dashboard">
|
<NuxtLink
|
||||||
|
to="/dashboard"
|
||||||
|
class="tab button-animation"
|
||||||
|
:title="formatMessage(commonMessages.dashboardLabel)"
|
||||||
|
>
|
||||||
<ChartIcon />
|
<ChartIcon />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
<button
|
<button
|
||||||
class="tab button-animation"
|
class="tab button-animation"
|
||||||
title="Toggle Mobile Menu"
|
:title="formatMessage(messages.toggleMenu)"
|
||||||
@click="toggleMobileMenu()"
|
@click="toggleMobileMenu()"
|
||||||
>
|
>
|
||||||
<template v-if="!auth.user">
|
<template v-if="!auth.user">
|
||||||
@@ -285,7 +303,7 @@
|
|||||||
:src="auth.user.avatar_url"
|
:src="auth.user.avatar_url"
|
||||||
class="user-icon"
|
class="user-icon"
|
||||||
:class="{ expanded: isMobileMenuOpen }"
|
:class="{ expanded: isMobileMenuOpen }"
|
||||||
alt="Your avatar"
|
:alt="formatMessage(messages.yourAvatarAlt)"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
circle
|
circle
|
||||||
/>
|
/>
|
||||||
@@ -300,17 +318,24 @@
|
|||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<div class="logo-info" role="region" aria-label="Modrinth information">
|
<div class="logo-info" role="region" aria-label="Modrinth information">
|
||||||
<BrandTextLogo aria-hidden="true" class="text-logo" @click="developerModeIncrement()" />
|
<BrandTextLogo
|
||||||
|
aria-hidden="true"
|
||||||
|
class="text-logo button-base"
|
||||||
|
@click="developerModeIncrement()"
|
||||||
|
/>
|
||||||
<p>
|
<p>
|
||||||
Modrinth is
|
<IntlFormatted :message-id="footerMessages.openSource">
|
||||||
<a
|
<template #github-link="{ children }">
|
||||||
:target="$external()"
|
<a
|
||||||
href="https://github.com/modrinth"
|
:target="$external()"
|
||||||
class="text-link"
|
href="https://github.com/modrinth"
|
||||||
rel="noopener"
|
class="text-link"
|
||||||
>
|
rel="noopener"
|
||||||
open source</a
|
>
|
||||||
>.
|
<component :is="() => children" />
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</IntlFormatted>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{{ config.public.owner }}/{{ config.public.slug }} {{ config.public.branch }}@<a
|
{{ config.public.owner }}/{{ config.public.slug }} {{ config.public.branch }}@<a
|
||||||
@@ -331,23 +356,32 @@
|
|||||||
<p>© Rinth, Inc.</p>
|
<p>© Rinth, Inc.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="links links-1" role="region" aria-label="Legal">
|
<div class="links links-1" role="region" aria-label="Legal">
|
||||||
<h4 aria-hidden="true">Company</h4>
|
<h4 aria-hidden="true">{{ formatMessage(footerMessages.companyTitle) }}</h4>
|
||||||
<nuxt-link to="/legal/terms"> Terms</nuxt-link>
|
<nuxt-link to="/legal/terms"> {{ formatMessage(footerMessages.terms) }}</nuxt-link>
|
||||||
<nuxt-link to="/legal/privacy"> Privacy</nuxt-link>
|
<nuxt-link to="/legal/privacy"> {{ formatMessage(footerMessages.privacy) }}</nuxt-link>
|
||||||
<nuxt-link to="/legal/rules"> Rules</nuxt-link>
|
<nuxt-link to="/legal/rules"> {{ formatMessage(footerMessages.rules) }}</nuxt-link>
|
||||||
<a :target="$external()" href="https://careers.modrinth.com">
|
<a :target="$external()" href="https://careers.modrinth.com">
|
||||||
Careers <span v-if="false" class="count-bubble">0</span>
|
{{ formatMessage(footerMessages.careers) }}
|
||||||
|
<span v-if="false" class="count-bubble">0</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="links links-2" role="region" aria-label="Resources">
|
<div class="links links-2" role="region" aria-label="Resources">
|
||||||
<h4 aria-hidden="true">Resources</h4>
|
<h4 aria-hidden="true">{{ formatMessage(footerMessages.resourcesTitle) }}</h4>
|
||||||
<a :target="$external()" href="https://support.modrinth.com">Support</a>
|
<a :target="$external()" href="https://support.modrinth.com">
|
||||||
<a :target="$external()" href="https://blog.modrinth.com">Blog</a>
|
{{ formatMessage(footerMessages.support) }}
|
||||||
<a :target="$external()" href="https://docs.modrinth.com">Docs</a>
|
</a>
|
||||||
<a :target="$external()" href="https://status.modrinth.com">Status</a>
|
<a :target="$external()" href="https://blog.modrinth.com">
|
||||||
|
{{ formatMessage(footerMessages.blog) }}
|
||||||
|
</a>
|
||||||
|
<a :target="$external()" href="https://docs.modrinth.com">
|
||||||
|
{{ formatMessage(footerMessages.docs) }}
|
||||||
|
</a>
|
||||||
|
<a :target="$external()" href="https://status.modrinth.com">
|
||||||
|
{{ formatMessage(footerMessages.status) }}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="links links-3" role="region" aria-label="Interact">
|
<div class="links links-3" role="region" aria-label="Interact">
|
||||||
<h4 aria-hidden="true">Interact</h4>
|
<h4 aria-hidden="true">{{ formatMessage(footerMessages.interactTitle) }}</h4>
|
||||||
<a rel="noopener" :target="$external()" href="https://discord.modrinth.com"> Discord </a>
|
<a rel="noopener" :target="$external()" href="https://discord.modrinth.com"> Discord </a>
|
||||||
<a rel="noopener" :target="$external()" href="https://x.com/modrinth"> X (Twitter) </a>
|
<a rel="noopener" :target="$external()" href="https://x.com/modrinth"> X (Twitter) </a>
|
||||||
<a rel="noopener" :target="$external()" href="https://floss.social/@modrinth"> Mastodon </a>
|
<a rel="noopener" :target="$external()" href="https://floss.social/@modrinth"> Mastodon </a>
|
||||||
@@ -358,20 +392,20 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<nuxt-link class="btn btn-outline btn-primary" to="/app">
|
<nuxt-link class="btn btn-outline btn-primary" to="/app">
|
||||||
<DownloadIcon aria-hidden="true" />
|
<DownloadIcon aria-hidden="true" />
|
||||||
Get Modrinth App
|
{{ formatMessage(messages.getModrinthApp) }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<button class="iconified-button raised-button" @click="changeTheme">
|
<button class="iconified-button raised-button" @click="changeTheme">
|
||||||
<MoonIcon v-if="$colorMode.value === 'light'" aria-hidden="true" />
|
<MoonIcon v-if="$colorMode.value === 'light'" aria-hidden="true" />
|
||||||
<SunIcon v-else aria-hidden="true" />
|
<SunIcon v-else aria-hidden="true" />
|
||||||
Change theme
|
{{ formatMessage(messages.changeTheme) }}
|
||||||
</button>
|
</button>
|
||||||
<nuxt-link class="iconified-button raised-button" to="/settings">
|
<nuxt-link class="iconified-button raised-button" to="/settings">
|
||||||
<SettingsIcon aria-hidden="true" />
|
<SettingsIcon aria-hidden="true" />
|
||||||
Settings
|
{{ formatMessage(commonMessages.settingsLabel) }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="not-affiliated-notice">
|
<div class="not-affiliated-notice">
|
||||||
NOT AN OFFICIAL MINECRAFT PRODUCT. NOT APPROVED BY OR ASSOCIATED WITH MOJANG.
|
{{ formatMessage(footerMessages.legalDisclaimer) }}
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
@@ -397,6 +431,8 @@ import ChartIcon from '~/assets/images/utils/chart.svg'
|
|||||||
import NavRow from '~/components/ui/NavRow.vue'
|
import NavRow from '~/components/ui/NavRow.vue'
|
||||||
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
||||||
import Avatar from '~/components/ui/Avatar.vue'
|
import Avatar from '~/components/ui/Avatar.vue'
|
||||||
|
import { getProjectTypeMessage } from '~/utils/i18n-project-type.ts'
|
||||||
|
import { commonMessages } from '~/utils/common-messages'
|
||||||
|
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
@@ -408,6 +444,131 @@ const tags = useTags()
|
|||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const link = config.public.siteUrl + route.path.replace(/\/+$/, '')
|
const link = config.public.siteUrl + route.path.replace(/\/+$/, '')
|
||||||
|
|
||||||
|
const verifyEmailBannerMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
id: 'layout.banner.verify-email.title',
|
||||||
|
defaultMessage: 'For security purposes, please verify your email address on Modrinth.',
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
id: 'layout.banner.verify-email.action',
|
||||||
|
defaultMessage: 'Re-send verification email',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const addEmailBannerMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
id: 'layout.banner.add-email.title',
|
||||||
|
defaultMessage: 'For security purposes, please enter your email on Modrinth.',
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
id: 'layout.banner.add-email.button',
|
||||||
|
defaultMessage: 'Visit account settings',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const stagingBannerMessages = defineMessages({
|
||||||
|
title: {
|
||||||
|
id: 'layout.banner.staging.title',
|
||||||
|
defaultMessage: 'You’re viewing Modrinth’s staging environment.',
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
id: 'layout.banner.staging.description',
|
||||||
|
defaultMessage:
|
||||||
|
'The staging environment is running on a copy of the production Modrinth database. This is used for testing and debugging purposes, and may be running in-development versions of the Modrinth backend or frontend newer than the production instance.',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const navMenuMessages = defineMessages({
|
||||||
|
home: {
|
||||||
|
id: 'layout.nav.home',
|
||||||
|
defaultMessage: 'Home',
|
||||||
|
},
|
||||||
|
search: {
|
||||||
|
id: 'layout.nav.search',
|
||||||
|
defaultMessage: 'Search',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
visitYourProfile: {
|
||||||
|
id: 'layout.label.visit-your-profile',
|
||||||
|
defaultMessage: 'Visit your profile',
|
||||||
|
},
|
||||||
|
toggleMenu: {
|
||||||
|
id: 'layout.menu-toggle.action',
|
||||||
|
defaultMessage: 'Toggle menu',
|
||||||
|
},
|
||||||
|
yourAvatarAlt: {
|
||||||
|
id: 'layout.avatar.alt',
|
||||||
|
defaultMessage: 'Your avatar',
|
||||||
|
},
|
||||||
|
getModrinthApp: {
|
||||||
|
id: 'layout.action.get-modrinth-app',
|
||||||
|
defaultMessage: 'Get Modrinth App',
|
||||||
|
},
|
||||||
|
changeTheme: {
|
||||||
|
id: 'layout.action.change-theme',
|
||||||
|
defaultMessage: 'Change theme',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const footerMessages = defineMessages({
|
||||||
|
openSource: {
|
||||||
|
id: 'layout.footer.open-source',
|
||||||
|
defaultMessage: 'Modrinth is <github-link>open source</github-link>.',
|
||||||
|
},
|
||||||
|
companyTitle: {
|
||||||
|
id: 'layout.footer.company.title',
|
||||||
|
defaultMessage: 'Company',
|
||||||
|
},
|
||||||
|
terms: {
|
||||||
|
id: 'layout.footer.company.terms',
|
||||||
|
defaultMessage: 'Terms',
|
||||||
|
},
|
||||||
|
privacy: {
|
||||||
|
id: 'layout.footer.company.privacy',
|
||||||
|
defaultMessage: 'Privacy',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
id: 'layout.footer.company.rules',
|
||||||
|
defaultMessage: 'Rules',
|
||||||
|
},
|
||||||
|
careers: {
|
||||||
|
id: 'layout.footer.company.careers',
|
||||||
|
defaultMessage: 'Careers',
|
||||||
|
},
|
||||||
|
resourcesTitle: {
|
||||||
|
id: 'layout.footer.resources.title',
|
||||||
|
defaultMessage: 'Resources',
|
||||||
|
},
|
||||||
|
support: {
|
||||||
|
id: 'layout.footer.resources.support',
|
||||||
|
defaultMessage: 'Support',
|
||||||
|
},
|
||||||
|
blog: {
|
||||||
|
id: 'layout.footer.resources.blog',
|
||||||
|
defaultMessage: 'Blog',
|
||||||
|
},
|
||||||
|
docs: {
|
||||||
|
id: 'layout.footer.resources.docs',
|
||||||
|
defaultMessage: 'Docs',
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
id: 'layout.footer.resources.status',
|
||||||
|
defaultMessage: 'Status',
|
||||||
|
},
|
||||||
|
interactTitle: {
|
||||||
|
id: 'layout.footer.interact.title',
|
||||||
|
defaultMessage: 'Interact',
|
||||||
|
},
|
||||||
|
legalDisclaimer: {
|
||||||
|
id: 'layout.footer.legal-disclaimer',
|
||||||
|
defaultMessage:
|
||||||
|
'NOT AN OFFICIAL MINECRAFT SERVICE. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT.',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
link: [
|
link: [
|
||||||
{
|
{
|
||||||
@@ -416,14 +577,15 @@ useHead({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
const description =
|
|
||||||
'Download Minecraft mods, plugins, datapacks, shaders, resourcepacks, and modpacks on Modrinth. ' +
|
|
||||||
'Discover and publish projects on Modrinth with a modern, easy to use interface and API.'
|
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: 'Modrinth',
|
title: 'Modrinth',
|
||||||
description,
|
description: () =>
|
||||||
|
formatMessage({
|
||||||
|
id: 'layout.meta.description',
|
||||||
|
defaultMessage:
|
||||||
|
'Download Minecraft mods, plugins, datapacks, shaders, resourcepacks, and modpacks on Modrinth. ' +
|
||||||
|
'Discover and publish projects on Modrinth with a modern, easy to use interface and API.',
|
||||||
|
}),
|
||||||
publisher: 'Modrinth',
|
publisher: 'Modrinth',
|
||||||
themeColor: '#1bd96a',
|
themeColor: '#1bd96a',
|
||||||
colorScheme: 'dark light',
|
colorScheme: 'dark light',
|
||||||
@@ -431,7 +593,11 @@ useSeoMeta({
|
|||||||
// OpenGraph
|
// OpenGraph
|
||||||
ogTitle: 'Modrinth',
|
ogTitle: 'Modrinth',
|
||||||
ogSiteName: 'Modrinth',
|
ogSiteName: 'Modrinth',
|
||||||
ogDescription: 'Discover and publish Minecraft content!',
|
ogDescription: () =>
|
||||||
|
formatMessage({
|
||||||
|
id: 'layout.meta.og-description',
|
||||||
|
defaultMessage: 'Discover and publish Minecraft content!',
|
||||||
|
}),
|
||||||
ogType: 'website',
|
ogType: 'website',
|
||||||
ogImage: 'https://cdn.modrinth.com/modrinth-new.png',
|
ogImage: 'https://cdn.modrinth.com/modrinth-new.png',
|
||||||
ogUrl: link,
|
ogUrl: link,
|
||||||
@@ -441,12 +607,67 @@ useSeoMeta({
|
|||||||
twitterSite: '@modrinth',
|
twitterSite: '@modrinth',
|
||||||
})
|
})
|
||||||
|
|
||||||
let developerModeCounter = 0
|
const developerModeCounter = ref(0)
|
||||||
|
|
||||||
|
const isDropdownOpen = ref(false)
|
||||||
|
const isMobileMenuOpen = ref(false)
|
||||||
|
const isBrowseMenuOpen = ref(false)
|
||||||
|
const navRoutes = computed(() => [
|
||||||
|
{
|
||||||
|
label: formatMessage(getProjectTypeMessage('mod', true)),
|
||||||
|
href: '/mods',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: formatMessage(getProjectTypeMessage('plugin', true)),
|
||||||
|
href: '/plugins',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: formatMessage(getProjectTypeMessage('datapack', true)),
|
||||||
|
href: '/datapacks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: formatMessage(getProjectTypeMessage('shader', true)),
|
||||||
|
href: '/shaders',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: formatMessage(getProjectTypeMessage('resourcepack', true)),
|
||||||
|
href: '/resourcepacks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: formatMessage(getProjectTypeMessage('modpack', true)),
|
||||||
|
href: '/modpacks',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (window && process.client) {
|
||||||
|
window.history.scrollRestoration = 'auto'
|
||||||
|
}
|
||||||
|
|
||||||
|
runAnalytics()
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.path,
|
||||||
|
() => {
|
||||||
|
isMobileMenuOpen.value = false
|
||||||
|
isBrowseMenuOpen.value = false
|
||||||
|
|
||||||
|
if (process.client) {
|
||||||
|
document.body.style.overflowY = 'scroll'
|
||||||
|
document.body.setAttribute('tabindex', '-1')
|
||||||
|
document.body.removeAttribute('tabindex')
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCurrentDate()
|
||||||
|
runAnalytics()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
function developerModeIncrement() {
|
function developerModeIncrement() {
|
||||||
if (developerModeCounter >= 5) {
|
if (developerModeCounter.value >= 5) {
|
||||||
cosmetics.value.developerMode = !cosmetics.value.developerMode
|
cosmetics.value.developerMode = !cosmetics.value.developerMode
|
||||||
developerModeCounter = 0
|
developerModeCounter.value = 0
|
||||||
if (cosmetics.value.developerMode) {
|
if (cosmetics.value.developerMode) {
|
||||||
app.$notify({
|
app.$notify({
|
||||||
group: 'main',
|
group: 'main',
|
||||||
@@ -463,7 +684,7 @@ function developerModeIncrement() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
developerModeCounter++
|
developerModeCounter.value++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,110 +692,43 @@ async function logoutUser() {
|
|||||||
await logout()
|
await logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function runAnalytics() {
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const replacedUrl = config.public.apiBaseUrl.replace('v2/', '')
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
$fetch(`${replacedUrl}analytics/view`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
url: window.location.href,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {})
|
||||||
|
.catch(() => {})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function toggleMobileMenu() {
|
||||||
|
isMobileMenuOpen.value = !isMobileMenuOpen.value
|
||||||
|
if (isMobileMenuOpen.value) {
|
||||||
|
isBrowseMenuOpen.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function toggleBrowseMenu() {
|
||||||
|
isBrowseMenuOpen.value = !isBrowseMenuOpen.value
|
||||||
|
|
||||||
|
if (isBrowseMenuOpen.value) {
|
||||||
|
isMobileMenuOpen.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function changeTheme() {
|
||||||
|
updateTheme(app.$colorMode.value === 'dark' ? 'light' : 'dark', true)
|
||||||
|
}
|
||||||
|
|
||||||
function hideStagingBanner() {
|
function hideStagingBanner() {
|
||||||
cosmetics.value.hideStagingBanner = true
|
cosmetics.value.hideStagingBanner = true
|
||||||
saveCosmetics()
|
saveCosmetics()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>
|
|
||||||
export default defineNuxtComponent({
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isDropdownOpen: false,
|
|
||||||
isMobileMenuOpen: false,
|
|
||||||
isBrowseMenuOpen: false,
|
|
||||||
registeredSkipLink: null,
|
|
||||||
hideDropdown: false,
|
|
||||||
navRoutes: [
|
|
||||||
{
|
|
||||||
label: 'Mods',
|
|
||||||
href: '/mods',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Plugins',
|
|
||||||
href: '/plugins',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Data Packs',
|
|
||||||
href: '/datapacks',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Shaders',
|
|
||||||
href: '/shaders',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Resource Packs',
|
|
||||||
href: '/resourcepacks',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Modpacks',
|
|
||||||
href: '/modpacks',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isOnSearchPage() {
|
|
||||||
return this.navRoutes.some((route) => this.$route.path.startsWith(route.href))
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'$route.path'() {
|
|
||||||
this.isMobileMenuOpen = false
|
|
||||||
this.isBrowseMenuOpen = false
|
|
||||||
|
|
||||||
if (process.client) {
|
|
||||||
document.body.style.overflowY = 'scroll'
|
|
||||||
document.body.setAttribute('tabindex', '-1')
|
|
||||||
document.body.removeAttribute('tabindex')
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCurrentDate()
|
|
||||||
this.runAnalytics()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
if (process.client && window) {
|
|
||||||
window.history.scrollRestoration = 'auto'
|
|
||||||
}
|
|
||||||
|
|
||||||
this.runAnalytics()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
runAnalytics() {
|
|
||||||
const config = useRuntimeConfig()
|
|
||||||
const replacedUrl = config.public.apiBaseUrl.replace('v2/', '')
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
$fetch(`${replacedUrl}analytics/view`, {
|
|
||||||
method: 'POST',
|
|
||||||
body: {
|
|
||||||
url: window.location.href,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() => {})
|
|
||||||
.catch(() => {})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
toggleMobileMenu() {
|
|
||||||
this.isMobileMenuOpen = !this.isMobileMenuOpen
|
|
||||||
if (this.isMobileMenuOpen) {
|
|
||||||
this.isBrowseMenuOpen = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggleBrowseMenu() {
|
|
||||||
this.isBrowseMenuOpen = !this.isBrowseMenuOpen
|
|
||||||
|
|
||||||
if (this.isBrowseMenuOpen) {
|
|
||||||
this.isMobileMenuOpen = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeTheme() {
|
|
||||||
updateTheme(this.$colorMode.value === 'dark' ? 'light' : 'dark', true)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '~/assets/styles/global.scss';
|
@import '~/assets/styles/global.scss';
|
||||||
|
|||||||
@@ -65,9 +65,6 @@
|
|||||||
"auth.sign-in.2fa.placeholder": {
|
"auth.sign-in.2fa.placeholder": {
|
||||||
"message": "Enter code..."
|
"message": "Enter code..."
|
||||||
},
|
},
|
||||||
"auth.sign-in.action.sign-in": {
|
|
||||||
"message": "Sign in"
|
|
||||||
},
|
|
||||||
"auth.sign-in.additional-options": {
|
"auth.sign-in.additional-options": {
|
||||||
"message": "<forgot-password-link>Forgot password?</forgot-password-link> • <create-account-link>Create an account</create-account-link>"
|
"message": "<forgot-password-link>Forgot password?</forgot-password-link> • <create-account-link>Create an account</create-account-link>"
|
||||||
},
|
},
|
||||||
@@ -107,9 +104,6 @@
|
|||||||
"auth.sign-up.password.label": {
|
"auth.sign-up.password.label": {
|
||||||
"message": "Password"
|
"message": "Password"
|
||||||
},
|
},
|
||||||
"auth.sign-up.sign-in-option.action": {
|
|
||||||
"message": "Sign in"
|
|
||||||
},
|
|
||||||
"auth.sign-up.sign-in-option.title": {
|
"auth.sign-up.sign-in-option.title": {
|
||||||
"message": "Already have an account?"
|
"message": "Already have an account?"
|
||||||
},
|
},
|
||||||
@@ -179,6 +173,9 @@
|
|||||||
"button.continue": {
|
"button.continue": {
|
||||||
"message": "Continue"
|
"message": "Continue"
|
||||||
},
|
},
|
||||||
|
"button.create-a-project": {
|
||||||
|
"message": "Create a project"
|
||||||
|
},
|
||||||
"button.edit": {
|
"button.edit": {
|
||||||
"message": "Edit"
|
"message": "Edit"
|
||||||
},
|
},
|
||||||
@@ -188,6 +185,12 @@
|
|||||||
"button.save-changes": {
|
"button.save-changes": {
|
||||||
"message": "Save changes"
|
"message": "Save changes"
|
||||||
},
|
},
|
||||||
|
"button.sign-in": {
|
||||||
|
"message": "Sign in"
|
||||||
|
},
|
||||||
|
"button.sign-out": {
|
||||||
|
"message": "Sign out"
|
||||||
|
},
|
||||||
"collection.button.delete-icon": {
|
"collection.button.delete-icon": {
|
||||||
"message": "Delete icon"
|
"message": "Delete icon"
|
||||||
},
|
},
|
||||||
@@ -290,6 +293,9 @@
|
|||||||
"label.created-ago": {
|
"label.created-ago": {
|
||||||
"message": "Created {ago}"
|
"message": "Created {ago}"
|
||||||
},
|
},
|
||||||
|
"label.dashboard": {
|
||||||
|
"message": "Dashboard"
|
||||||
|
},
|
||||||
"label.delete": {
|
"label.delete": {
|
||||||
"message": "Delete"
|
"message": "Delete"
|
||||||
},
|
},
|
||||||
@@ -302,6 +308,12 @@
|
|||||||
"label.followed-projects": {
|
"label.followed-projects": {
|
||||||
"message": "Followed projects"
|
"message": "Followed projects"
|
||||||
},
|
},
|
||||||
|
"label.moderation": {
|
||||||
|
"message": "Moderation"
|
||||||
|
},
|
||||||
|
"label.notifications": {
|
||||||
|
"message": "Notifications"
|
||||||
|
},
|
||||||
"label.password": {
|
"label.password": {
|
||||||
"message": "Password"
|
"message": "Password"
|
||||||
},
|
},
|
||||||
@@ -314,6 +326,9 @@
|
|||||||
"label.scopes": {
|
"label.scopes": {
|
||||||
"message": "Scopes"
|
"message": "Scopes"
|
||||||
},
|
},
|
||||||
|
"label.settings": {
|
||||||
|
"message": "Settings"
|
||||||
|
},
|
||||||
"label.title": {
|
"label.title": {
|
||||||
"message": "Title"
|
"message": "Title"
|
||||||
},
|
},
|
||||||
@@ -323,6 +338,90 @@
|
|||||||
"label.visibility": {
|
"label.visibility": {
|
||||||
"message": "Visibility"
|
"message": "Visibility"
|
||||||
},
|
},
|
||||||
|
"layout.action.change-theme": {
|
||||||
|
"message": "Change theme"
|
||||||
|
},
|
||||||
|
"layout.action.get-modrinth-app": {
|
||||||
|
"message": "Get Modrinth App"
|
||||||
|
},
|
||||||
|
"layout.avatar.alt": {
|
||||||
|
"message": "Your avatar"
|
||||||
|
},
|
||||||
|
"layout.banner.add-email.button": {
|
||||||
|
"message": "Visit account settings"
|
||||||
|
},
|
||||||
|
"layout.banner.add-email.title": {
|
||||||
|
"message": "For security purposes, please enter your email on Modrinth."
|
||||||
|
},
|
||||||
|
"layout.banner.staging.description": {
|
||||||
|
"message": "The staging environment is running on a copy of the production Modrinth database. This is used for testing and debugging purposes, and may be running in-development versions of the Modrinth backend or frontend newer than the production instance."
|
||||||
|
},
|
||||||
|
"layout.banner.staging.title": {
|
||||||
|
"message": "You’re viewing Modrinth’s staging environment."
|
||||||
|
},
|
||||||
|
"layout.banner.verify-email.action": {
|
||||||
|
"message": "Re-send verification email"
|
||||||
|
},
|
||||||
|
"layout.banner.verify-email.title": {
|
||||||
|
"message": "For security purposes, please verify your email address on Modrinth."
|
||||||
|
},
|
||||||
|
"layout.footer.company.careers": {
|
||||||
|
"message": "Careers"
|
||||||
|
},
|
||||||
|
"layout.footer.company.privacy": {
|
||||||
|
"message": "Privacy"
|
||||||
|
},
|
||||||
|
"layout.footer.company.rules": {
|
||||||
|
"message": "Rules"
|
||||||
|
},
|
||||||
|
"layout.footer.company.terms": {
|
||||||
|
"message": "Terms"
|
||||||
|
},
|
||||||
|
"layout.footer.company.title": {
|
||||||
|
"message": "Company"
|
||||||
|
},
|
||||||
|
"layout.footer.interact.title": {
|
||||||
|
"message": "Interact"
|
||||||
|
},
|
||||||
|
"layout.footer.legal-disclaimer": {
|
||||||
|
"message": "NOT AN OFFICIAL MINECRAFT SERVICE. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT."
|
||||||
|
},
|
||||||
|
"layout.footer.open-source": {
|
||||||
|
"message": "Modrinth is <github-link>open source</github-link>."
|
||||||
|
},
|
||||||
|
"layout.footer.resources.blog": {
|
||||||
|
"message": "Blog"
|
||||||
|
},
|
||||||
|
"layout.footer.resources.docs": {
|
||||||
|
"message": "Docs"
|
||||||
|
},
|
||||||
|
"layout.footer.resources.status": {
|
||||||
|
"message": "Status"
|
||||||
|
},
|
||||||
|
"layout.footer.resources.support": {
|
||||||
|
"message": "Support"
|
||||||
|
},
|
||||||
|
"layout.footer.resources.title": {
|
||||||
|
"message": "Resources"
|
||||||
|
},
|
||||||
|
"layout.label.visit-your-profile": {
|
||||||
|
"message": "Visit your profile"
|
||||||
|
},
|
||||||
|
"layout.menu-toggle.action": {
|
||||||
|
"message": "Toggle menu"
|
||||||
|
},
|
||||||
|
"layout.meta.description": {
|
||||||
|
"message": "Download Minecraft mods, plugins, datapacks, shaders, resourcepacks, and modpacks on Modrinth. Discover and publish projects on Modrinth with a modern, easy to use interface and API."
|
||||||
|
},
|
||||||
|
"layout.meta.og-description": {
|
||||||
|
"message": "Discover and publish Minecraft content!"
|
||||||
|
},
|
||||||
|
"layout.nav.home": {
|
||||||
|
"message": "Home"
|
||||||
|
},
|
||||||
|
"layout.nav.search": {
|
||||||
|
"message": "Search"
|
||||||
|
},
|
||||||
"notification.error.title": {
|
"notification.error.title": {
|
||||||
"message": "An error occurred"
|
"message": "An error occurred"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<button class="btn btn-primary continue-btn" @click="begin2FASignIn">
|
<button class="btn btn-primary continue-btn" @click="begin2FASignIn">
|
||||||
{{ formatMessage(messages.signInButton) }} <RightArrowIcon />
|
{{ formatMessage(commonMessages.signInButton) }} <RightArrowIcon />
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<NuxtTurnstile ref="turnstile" v-model="token" class="turnstile" />
|
<NuxtTurnstile ref="turnstile" v-model="token" class="turnstile" />
|
||||||
|
|
||||||
<button class="btn btn-primary continue-btn centered-btn" @click="beginPasswordSignIn()">
|
<button class="btn btn-primary continue-btn centered-btn" @click="beginPasswordSignIn()">
|
||||||
{{ formatMessage(messages.signInButton) }} <RightArrowIcon />
|
{{ formatMessage(commonMessages.signInButton) }} <RightArrowIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="auth-form__additional-options">
|
<div class="auth-form__additional-options">
|
||||||
@@ -135,10 +135,6 @@ const messages = defineMessages({
|
|||||||
id: 'auth.sign-in.password.label',
|
id: 'auth.sign-in.password.label',
|
||||||
defaultMessage: 'Password',
|
defaultMessage: 'Password',
|
||||||
},
|
},
|
||||||
signInButton: {
|
|
||||||
id: 'auth.sign-in.action.sign-in',
|
|
||||||
defaultMessage: 'Sign in',
|
|
||||||
},
|
|
||||||
signInWithLabel: {
|
signInWithLabel: {
|
||||||
id: 'auth.sign-in.sign-in-with',
|
id: 'auth.sign-in.sign-in-with',
|
||||||
defaultMessage: 'Sign in with',
|
defaultMessage: 'Sign in with',
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
<div class="auth-form__additional-options">
|
<div class="auth-form__additional-options">
|
||||||
{{ formatMessage(messages.alreadyHaveAccountLabel) }}
|
{{ formatMessage(messages.alreadyHaveAccountLabel) }}
|
||||||
<NuxtLink class="text-link" :to="signInLink">
|
<NuxtLink class="text-link" :to="signInLink">
|
||||||
{{ formatMessage(messages.signInLabel) }}
|
{{ formatMessage(commonMessages.signInButton) }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -185,10 +185,6 @@ const messages = defineMessages({
|
|||||||
id: 'auth.sign-up.sign-in-option.title',
|
id: 'auth.sign-up.sign-in-option.title',
|
||||||
defaultMessage: 'Already have an account?',
|
defaultMessage: 'Already have an account?',
|
||||||
},
|
},
|
||||||
signInLabel: {
|
|
||||||
id: 'auth.sign-up.sign-in-option.action',
|
|
||||||
defaultMessage: 'Sign in',
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<button class="iconified-button brand-button" @click="$refs.modal_creation.show()">
|
<button class="iconified-button brand-button" @click="$refs.modal_creation.show()">
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
Create a project
|
{{ formatMessage(commonMessages.createAProjectButton) }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -339,9 +339,11 @@ export default defineNuxtComponent({
|
|||||||
DescendingIcon,
|
DescendingIcon,
|
||||||
},
|
},
|
||||||
async setup() {
|
async setup() {
|
||||||
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const user = await useUser()
|
const user = await useUser()
|
||||||
await initUserProjects()
|
await initUserProjects()
|
||||||
return { user: ref(user) }
|
return { formatMessage, user: ref(user) }
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -163,7 +163,7 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<Button color="primary" @click="$refs.modal_creation.show()">
|
<Button color="primary" @click="$refs.modal_creation.show()">
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
Create a project
|
{{ formatMessage(commonMessages.createAProjectButton) }}
|
||||||
</Button>
|
</Button>
|
||||||
<OrganizationProjectTransferModal
|
<OrganizationProjectTransferModal
|
||||||
:projects="usersOwnedProjects || []"
|
:projects="usersOwnedProjects || []"
|
||||||
@@ -321,6 +321,8 @@ import {
|
|||||||
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
||||||
import OrganizationProjectTransferModal from '~/components/ui/OrganizationProjectTransferModal.vue'
|
import OrganizationProjectTransferModal from '~/components/ui/OrganizationProjectTransferModal.vue'
|
||||||
|
|
||||||
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const { organization, projects, refresh } = inject('organizationContext')
|
const { organization, projects, refresh } = inject('organizationContext')
|
||||||
|
|
||||||
const auth = await useAuth()
|
const auth = await useAuth()
|
||||||
|
|||||||
@@ -15,10 +15,18 @@ export const commonMessages = defineMessages({
|
|||||||
id: 'button.continue',
|
id: 'button.continue',
|
||||||
defaultMessage: 'Continue',
|
defaultMessage: 'Continue',
|
||||||
},
|
},
|
||||||
|
createAProjectButton: {
|
||||||
|
id: 'button.create-a-project',
|
||||||
|
defaultMessage: 'Create a project',
|
||||||
|
},
|
||||||
createdAgoLabel: {
|
createdAgoLabel: {
|
||||||
id: 'label.created-ago',
|
id: 'label.created-ago',
|
||||||
defaultMessage: 'Created {ago}',
|
defaultMessage: 'Created {ago}',
|
||||||
},
|
},
|
||||||
|
dashboardLabel: {
|
||||||
|
id: 'label.dashboard',
|
||||||
|
defaultMessage: 'Dashboard',
|
||||||
|
},
|
||||||
dateAtTimeTooltip: {
|
dateAtTimeTooltip: {
|
||||||
id: 'tooltip.date-at-time',
|
id: 'tooltip.date-at-time',
|
||||||
defaultMessage: '{date, date, long} at {time, time, short}',
|
defaultMessage: '{date, date, long} at {time, time, short}',
|
||||||
@@ -59,6 +67,14 @@ export const commonMessages = defineMessages({
|
|||||||
id: 'input.view.list',
|
id: 'input.view.list',
|
||||||
defaultMessage: 'List view',
|
defaultMessage: 'List view',
|
||||||
},
|
},
|
||||||
|
moderationLabel: {
|
||||||
|
id: 'label.moderation',
|
||||||
|
defaultMessage: 'Moderation',
|
||||||
|
},
|
||||||
|
notificationsLabel: {
|
||||||
|
id: 'label.notifications',
|
||||||
|
defaultMessage: 'Notifications',
|
||||||
|
},
|
||||||
privateLabel: {
|
privateLabel: {
|
||||||
id: 'collection.label.private',
|
id: 'collection.label.private',
|
||||||
defaultMessage: 'Private',
|
defaultMessage: 'Private',
|
||||||
@@ -87,6 +103,18 @@ export const commonMessages = defineMessages({
|
|||||||
id: 'label.scopes',
|
id: 'label.scopes',
|
||||||
defaultMessage: 'Scopes',
|
defaultMessage: 'Scopes',
|
||||||
},
|
},
|
||||||
|
settingsLabel: {
|
||||||
|
id: 'label.settings',
|
||||||
|
defaultMessage: 'Settings',
|
||||||
|
},
|
||||||
|
signInButton: {
|
||||||
|
id: 'button.sign-in',
|
||||||
|
defaultMessage: 'Sign in',
|
||||||
|
},
|
||||||
|
signOutButton: {
|
||||||
|
id: 'button.sign-out',
|
||||||
|
defaultMessage: 'Sign out',
|
||||||
|
},
|
||||||
titleLabel: {
|
titleLabel: {
|
||||||
id: 'label.title',
|
id: 'label.title',
|
||||||
defaultMessage: 'Title',
|
defaultMessage: 'Title',
|
||||||
|
|||||||
Reference in New Issue
Block a user