Add UI module translations to Modrinth App (#5489)

* Add UI module translations to Modrinth App

* Replace `await` with `eager: true`

---------

Co-authored-by: Calum H. <calum@modrinth.com>
This commit is contained in:
Jerozgen
2026-03-07 13:13:24 +03:00
committed by GitHub
parent 4b6de7526c
commit d4932d3089
8 changed files with 27 additions and 16 deletions

View File

@@ -8,14 +8,14 @@ import {
LOCALES, LOCALES,
useVIntl, useVIntl,
} from '@modrinth/ui' } from '@modrinth/ui'
import { ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { get, set } from '@/helpers/settings.ts' import { get, set } from '@/helpers/settings.ts'
import i18n from '@/i18n.config' import i18n from '@/i18n.config'
const { formatMessage } = useVIntl() const { formatMessage } = useVIntl()
const platform = formatMessage(languageSelectorMessages.platformApp) const platform = computed(() => formatMessage(languageSelectorMessages.platformApp))
const settings = ref(await get()) const settings = ref(await get())

View File

@@ -1,4 +1,5 @@
import { buildLocaleMessages, createMessageCompiler, type CrowdinMessages } from '@modrinth/ui' import { buildLocaleMessages, createMessageCompiler, type CrowdinMessages } from '@modrinth/ui'
import { uiLocaleModulesEager } from '@modrinth/ui/src/locales.eager.ts'
import { createI18n } from 'vue-i18n' import { createI18n } from 'vue-i18n'
const localeModules = import.meta.glob<{ default: CrowdinMessages }>('./locales/*/index.json', { const localeModules = import.meta.glob<{ default: CrowdinMessages }>('./locales/*/index.json', {
@@ -12,7 +13,7 @@ const i18n = createI18n({
messageCompiler: createMessageCompiler(), messageCompiler: createMessageCompiler(),
missingWarn: false, missingWarn: false,
fallbackWarn: false, fallbackWarn: false,
messages: buildLocaleMessages(localeModules), messages: buildLocaleMessages(localeModules, uiLocaleModulesEager),
}) })
export default i18n export default i18n

View File

@@ -3,8 +3,6 @@
import type { FunctionalComponent, SVGAttributes } from 'vue' import type { FunctionalComponent, SVGAttributes } from 'vue'
export type IconComponent = FunctionalComponent<SVGAttributes>
import _AffiliateIcon from './icons/affiliate.svg?component' import _AffiliateIcon from './icons/affiliate.svg?component'
import _AlignLeftIcon from './icons/align-left.svg?component' import _AlignLeftIcon from './icons/align-left.svg?component'
import _ArchiveIcon from './icons/archive.svg?component' import _ArchiveIcon from './icons/archive.svg?component'
@@ -380,6 +378,8 @@ import _XCircleIcon from './icons/x-circle.svg?component'
import _ZoomInIcon from './icons/zoom-in.svg?component' import _ZoomInIcon from './icons/zoom-in.svg?component'
import _ZoomOutIcon from './icons/zoom-out.svg?component' import _ZoomOutIcon from './icons/zoom-out.svg?component'
export type IconComponent = FunctionalComponent<SVGAttributes>
export const AffiliateIcon = _AffiliateIcon export const AffiliateIcon = _AffiliateIcon
export const AlignLeftIcon = _AlignLeftIcon export const AlignLeftIcon = _AlignLeftIcon
export const ArchiveIcon = _ArchiveIcon export const ArchiveIcon = _ArchiveIcon

View File

@@ -148,7 +148,7 @@ export const coreNags: Nag[] = [
}), }),
status: 'suggestion', status: 'suggestion',
shouldShow: (context: NagContext) => { shouldShow: (context: NagContext) => {
if (!!context.projectV3?.minecraft_server) return false if (context.projectV3?.minecraft_server) return false
const featuredGalleryImage = context.project.gallery?.find((img) => img.featured) const featuredGalleryImage = context.project.gallery?.find((img) => img.featured)
return context.project?.gallery?.length === 0 || !featuredGalleryImage return context.project?.gallery?.length === 0 || !featuredGalleryImage
}, },

View File

@@ -1,4 +1,5 @@
import { defineMessage } from '@modrinth/ui' import { defineMessage } from '@modrinth/ui'
import type { Nag, NagContext } from '../../types/nags' import type { Nag, NagContext } from '../../types/nags'
export const serverProjectsNags: Nag[] = [ export const serverProjectsNags: Nag[] = [

View File

@@ -21,7 +21,7 @@ const links: Stage = {
), ),
text: async (project, projectV3) => { text: async (project, projectV3) => {
let text let text
if (!!projectV3?.minecraft_server) if (projectV3?.minecraft_server)
text = (await import('../messages/checklist-text/links/server.md?raw')).default text = (await import('../messages/checklist-text/links/server.md?raw')).default
else text = (await import('../messages/checklist-text/links/base.md?raw')).default else text = (await import('../messages/checklist-text/links/base.md?raw')).default

View File

@@ -94,17 +94,20 @@ const LOCALE_CODES = new Set(LOCALES.map((l) => l.code))
* Usage: buildLocaleMessages(import.meta.glob('./locales/* /index.json', { eager: true })) * Usage: buildLocaleMessages(import.meta.glob('./locales/* /index.json', { eager: true }))
*/ */
export function buildLocaleMessages( export function buildLocaleMessages(
modules: Record<string, { default: CrowdinMessages }>, ...allModules: Record<string, { default: CrowdinMessages }>[]
): Record<string, Record<string, string>> { ): Record<string, Record<string, string>> {
const messages: Record<string, Record<string, string>> = {} const messages: Record<string, Record<string, string>> = {}
for (const [path, module] of Object.entries(modules)) { for (const modules of allModules) {
// Extract locale code from path like './locales/en-US/index.json' or './src/locales/en-US/index.json' for (const [path, module] of Object.entries(modules)) {
const match = path.match(/\/([^/]+)\/index\.json$/) // Extract locale code from path like './locales/en-US/index.json' or './src/locales/en-US/index.json'
if (match) { const match = path.match(/\/([^/]+)\/index\.json$/)
const locale = match[1] if (match) {
// Only include locales that are in our LOCALES list const locale = match[1]
if (LOCALE_CODES.has(locale)) { // Only include locales that are in our LOCALES list
messages[locale] = transformCrowdinMessages(module.default) if (LOCALE_CODES.has(locale)) {
const mergedMessages = messages[locale] ?? {}
messages[locale] = Object.assign(mergedMessages, transformCrowdinMessages(module.default))
}
} }
} }
} }

View File

@@ -0,0 +1,6 @@
import type { CrowdinMessages } from './composables/i18n'
export const uiLocaleModulesEager = import.meta.glob<{ default: CrowdinMessages }>(
'./locales/*/index.json',
{ eager: true },
)