i18n support

This commit is contained in:
Gauthier Roebroeck 2025-05-28 16:17:11 +08:00
parent 382a851b7d
commit 43238774b0
8 changed files with 119 additions and 30 deletions

View file

@ -35,12 +35,13 @@ export default defineConfigWithVueTs(
}
},
formatjs.configs.recommended,
{
plugins: {
formatjs,
},
rules: {
'formatjs/no-offset': 'error',
'formatjs/enforce-id': [
'error',
{

34
next-ui/i18n/en.json Normal file
View file

@ -0,0 +1,34 @@
{
"8dsA6c": {
"defaultMessage": "User Interface",
"description": "Drawer menu for User Interface"
},
"9yKJ2S": {
"defaultMessage": "Settings",
"description": "Drawer menu for Server Settings"
},
"BXkzdX": {
"defaultMessage": "Users",
"description": "Drawer menu for Users"
},
"IpvWiZ": {
"defaultMessage": "Server",
"description": "Drawer menu for Server"
},
"Nn5L5Q": {
"defaultMessage": "Announcements",
"description": "Drawer menu for Announcements"
},
"localename": {
"defaultMessage": "English",
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
},
"nGrxDH": {
"defaultMessage": "Updates",
"description": "Drawer menu for Updates"
},
"nr3gEG": {
"defaultMessage": "Metrics",
"description": "Drawer menu for Metrics"
}
}

14
next-ui/i18n/fr.json Normal file
View file

@ -0,0 +1,14 @@
{
"9yKJ2S": {
"defaultMessage": "Réglages",
"description": "Drawer menu for Server Settings"
},
"localename": {
"defaultMessage": "Français",
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
},
"IpvWiZ": {
"defaultMessage": "Serveur",
"description": "Drawer menu for Server"
}
}

View file

@ -11,7 +11,8 @@
"type-check": "vue-tsc --build --force",
"lint": "eslint . --fix",
"openapi-generate": "npx tsx ./openapi-generator.mts",
"i18n-extract": "formatjs extract \"src/**/*.{ts,tsx,vue}\" --ignore=\"**/*.d.ts\" --out-file src/i18n/en.json"
"i18n-extract": "formatjs extract \"src/**/*.{ts,tsx,vue}\" --ignore=\"**/*.d.ts\" --out-file src/i18n/en.json",
"i18n-compile": "formatjs compile-folder i18n src/i18n"
},
"dependencies": {
"@pinia/colada": "^0.16.1",

View file

@ -6,7 +6,11 @@
<template #activator="{ props }">
<v-list-item
v-bind="props"
title="Server"
:title="$formatMessage({
description: 'Drawer menu for Server',
defaultMessage: 'Server',
id: 'IpvWiZ'
})"
prepend-icon="mdi-cog"
>
<template #prepend>
@ -24,33 +28,44 @@
<v-list-item
to="/server/users"
title="Users"
:title="$formatMessage({
description: 'Drawer menu for Users',
defaultMessage: 'Users',
id: 'BXkzdX'
})"
/>
<v-list-item
to="/server/settings"
>
<v-list-item-title>
{{
$formatMessage({
description: 'Drawer menu for Server Settings',
defaultMessage: 'Settings',
id: '9yKJ2S'
})
}}
</v-list-item-title>
</v-list-item>
:title="$formatMessage({
description: 'Drawer menu for Server Settings',
defaultMessage: 'Settings',
id: '9yKJ2S'
})"
/>
<v-list-item
to="/server/ui"
title="User Interface"
:title="$formatMessage({
description: 'Drawer menu for User Interface',
defaultMessage: 'User Interface',
id: '8dsA6c'
})"
/>
<v-list-item
to="/server/metrics"
title="Metrics"
:title="$formatMessage({
description: 'Drawer menu for Metrics',
defaultMessage: 'Metrics',
id: 'nr3gEG'
})"
/>
<v-list-item
to="/server/announcements"
title="Announcements"
:title="$formatMessage({
description: 'Drawer menu for Announcements',
defaultMessage: 'Announcements',
id: 'Nn5L5Q'
})"
>
<template #append>
<v-badge
@ -64,7 +79,11 @@
<v-list-item
to="/server/updates"
title="Updates"
:title="$formatMessage({
description: 'Drawer menu for Updates',
defaultMessage: 'Updates',
id: 'nGrxDH'
})"
/>
</v-list-group>
</template>

View file

@ -1,10 +1,34 @@
{
"8dsA6c": {
"defaultMessage": "User Interface",
"description": "Drawer menu for User Interface"
},
"9yKJ2S": {
"defaultMessage": "Settings",
"description": "Drawer menu for Server Settings"
},
"BXkzdX": {
"defaultMessage": "Users",
"description": "Drawer menu for Users"
},
"IpvWiZ": {
"defaultMessage": "Server",
"description": "Drawer menu for Server"
},
"Nn5L5Q": {
"defaultMessage": "Announcements",
"description": "Drawer menu for Announcements"
},
"localename": {
"defaultMessage": "English",
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
},
"nGrxDH": {
"defaultMessage": "Updates",
"description": "Drawer menu for Updates"
},
"nr3gEG": {
"defaultMessage": "Metrics",
"description": "Drawer menu for Metrics"
}
}

View file

@ -1,10 +1,5 @@
{
"9yKJ2S": {
"defaultMessage": "Réglages",
"description": "Drawer menu for Server Settings"
},
"localename": {
"defaultMessage": "Français",
"description": "The name of the locale, shown in the language selection menu. Must be translated to the language's name"
}
}
"9yKJ2S": "Réglages",
"IpvWiZ": "Serveur",
"localename": "Français"
}

View file

@ -2,6 +2,7 @@ import {defineMessage} from 'vue-intl'
export const defaultLocale = 'en'
// eslint-disable-next-line
const localeName = defineMessage({
description: 'The name of the locale, shown in the language selection menu. Must be translated to the language\'s name',
defaultMessage: 'English',
@ -26,8 +27,8 @@ async function loadAvailableLocales(): Promise<Record<string, string>> {
const matched = path.match(/([A-Za-z0-9-_]+)\./i)
if (matched && matched.length > 1) {
const locale = matched[1]
const messages = await localeFiles[path]!() as Record<string, {defaultMessage: string}>
locales[locale!] = messages[localeName.id]!.defaultMessage
const messages = await localeFiles[path]!() as Record<string, string>
locales[locale!] = messages[localeName.id]!
}
}
return locales