mirror of
https://github.com/unraid/api.git
synced 2026-01-02 14:40:01 -06:00
Compare commits
1 Commits
v4.21.0
...
feat/trans
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b080501c1 |
@@ -114,6 +114,7 @@
|
||||
"graphql-subscriptions": "3.0.0",
|
||||
"graphql-tag": "2.12.6",
|
||||
"graphql-ws": "6.0.6",
|
||||
"i18next": "^25.5.2",
|
||||
"ini": "5.0.0",
|
||||
"ip": "2.0.1",
|
||||
"jose": "6.0.13",
|
||||
@@ -123,6 +124,7 @@
|
||||
"mustache": "4.2.0",
|
||||
"nest-authz": "2.17.0",
|
||||
"nest-commander": "3.19.0",
|
||||
"nestjs-i18n": "^10.5.1",
|
||||
"nestjs-pino": "4.4.0",
|
||||
"node-cache": "5.1.2",
|
||||
"node-window-polyfill": "1.0.4",
|
||||
|
||||
29
api/src/i18n/en/common.json
Normal file
29
api/src/i18n/en/common.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"hello": "Hello",
|
||||
"welcome": "Welcome to Unraid API",
|
||||
"server": {
|
||||
"started": "Server started successfully",
|
||||
"stopped": "Server stopped",
|
||||
"error": "Server error occurred"
|
||||
},
|
||||
"auth": {
|
||||
"unauthorized": "Unauthorized access",
|
||||
"forbidden": "Access forbidden",
|
||||
"invalidToken": "Invalid authentication token",
|
||||
"tokenExpired": "Authentication token expired",
|
||||
"loginSuccess": "Login successful",
|
||||
"logoutSuccess": "Logout successful"
|
||||
},
|
||||
"docker": {
|
||||
"containerStarted": "Container {{name}} started",
|
||||
"containerStopped": "Container {{name}} stopped",
|
||||
"containerRemoved": "Container {{name}} removed",
|
||||
"imageDeleted": "Image {{name}} deleted"
|
||||
},
|
||||
"vm": {
|
||||
"started": "Virtual machine {{name}} started",
|
||||
"stopped": "Virtual machine {{name}} stopped",
|
||||
"paused": "Virtual machine {{name}} paused",
|
||||
"resumed": "Virtual machine {{name}} resumed"
|
||||
}
|
||||
}
|
||||
38
api/src/i18n/en/errors.json
Normal file
38
api/src/i18n/en/errors.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"notFound": "Resource not found",
|
||||
"internalError": "Internal server error",
|
||||
"badRequest": "Bad request",
|
||||
"validation": {
|
||||
"required": "{{field}} is required",
|
||||
"invalid": "{{field}} is invalid",
|
||||
"minLength": "{{field}} must be at least {{min}} characters",
|
||||
"maxLength": "{{field}} must not exceed {{max}} characters",
|
||||
"email": "Invalid email format",
|
||||
"numeric": "{{field}} must be a number",
|
||||
"range": "{{field}} must be between {{min}} and {{max}}"
|
||||
},
|
||||
"docker": {
|
||||
"containerNotFound": "Container {{id}} not found",
|
||||
"imageNotFound": "Image {{id}} not found",
|
||||
"networkNotFound": "Network {{id}} not found",
|
||||
"volumeNotFound": "Volume {{id}} not found",
|
||||
"operationFailed": "Docker operation failed: {{error}}"
|
||||
},
|
||||
"vm": {
|
||||
"notFound": "Virtual machine {{name}} not found",
|
||||
"invalidState": "Invalid VM state for operation",
|
||||
"operationFailed": "VM operation failed: {{error}}"
|
||||
},
|
||||
"plugin": {
|
||||
"notFound": "Plugin {{name}} not found",
|
||||
"installFailed": "Failed to install plugin {{name}}",
|
||||
"uninstallFailed": "Failed to uninstall plugin {{name}}",
|
||||
"invalidManifest": "Invalid plugin manifest"
|
||||
},
|
||||
"file": {
|
||||
"notFound": "File not found: {{path}}",
|
||||
"accessDenied": "Access denied: {{path}}",
|
||||
"readError": "Failed to read file: {{path}}",
|
||||
"writeError": "Failed to write file: {{path}}"
|
||||
}
|
||||
}
|
||||
20
api/src/i18n/en/validation.json
Normal file
20
api/src/i18n/en/validation.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"isNotEmpty": "{{property}} should not be empty",
|
||||
"isEmail": "{{property}} must be a valid email",
|
||||
"isString": "{{property}} must be a string",
|
||||
"isNumber": "{{property}} must be a number",
|
||||
"isBoolean": "{{property}} must be a boolean",
|
||||
"isArray": "{{property}} must be an array",
|
||||
"isObject": "{{property}} must be an object",
|
||||
"isEnum": "{{property}} must be one of: {{values}}",
|
||||
"minLength": "{{property}} must be at least {{min}} characters",
|
||||
"maxLength": "{{property}} must not exceed {{max}} characters",
|
||||
"min": "{{property}} must be at least {{min}}",
|
||||
"max": "{{property}} must not exceed {{max}}",
|
||||
"matches": "{{property}} format is invalid",
|
||||
"isUUID": "{{property}} must be a valid UUID",
|
||||
"isURL": "{{property}} must be a valid URL",
|
||||
"isIP": "{{property}} must be a valid IP address",
|
||||
"isPort": "{{property}} must be a valid port number",
|
||||
"isPath": "{{property}} must be a valid path"
|
||||
}
|
||||
28
api/src/i18n/i18n.module.ts
Normal file
28
api/src/i18n/i18n.module.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { HeaderResolver, I18nModule, QueryResolver, AcceptLanguageResolver } from 'nestjs-i18n';
|
||||
import * as path from 'path';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
I18nModule.forRootAsync({
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
useFactory: (configService: ConfigService) => ({
|
||||
fallbackLanguage: 'en',
|
||||
loaderOptions: {
|
||||
path: path.join(__dirname),
|
||||
watch: configService.get('NODE_ENV') === 'development',
|
||||
},
|
||||
resolvers: [
|
||||
new QueryResolver(['lang', 'locale', 'l']),
|
||||
new HeaderResolver(['x-locale', 'x-lang']),
|
||||
new AcceptLanguageResolver(),
|
||||
],
|
||||
typesOutputPath: path.join(__dirname, '../../src/generated/i18n.generated.ts'),
|
||||
}),
|
||||
}),
|
||||
],
|
||||
exports: [I18nModule],
|
||||
})
|
||||
export class AppI18nModule {}
|
||||
36
api/src/i18n/i18n.service.example.ts
Normal file
36
api/src/i18n/i18n.service.example.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { I18nService, I18nContext } from 'nestjs-i18n';
|
||||
|
||||
@Injectable()
|
||||
export class ExampleI18nService {
|
||||
constructor(private readonly i18n: I18nService) {}
|
||||
|
||||
// Basic translation
|
||||
getWelcomeMessage(lang?: string): string {
|
||||
return this.i18n.translate('common.welcome', { lang });
|
||||
}
|
||||
|
||||
// Translation with interpolation
|
||||
getContainerStartedMessage(containerName: string, lang?: string): string {
|
||||
return this.i18n.translate('common.docker.containerStarted', {
|
||||
args: { name: containerName },
|
||||
lang,
|
||||
});
|
||||
}
|
||||
|
||||
// Using context from request
|
||||
async getErrorMessage(errorKey: string): Promise<string> {
|
||||
const context = I18nContext.current();
|
||||
return this.i18n.translate(`errors.${errorKey}`, {
|
||||
lang: context?.lang,
|
||||
});
|
||||
}
|
||||
|
||||
// Validation message with parameters
|
||||
getValidationMessage(field: string, min: number, max: number, lang?: string): string {
|
||||
return this.i18n.translate('errors.validation.range', {
|
||||
args: { field, min, max },
|
||||
lang,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { LoggerModule } from 'nestjs-pino';
|
||||
|
||||
import { apiLogger } from '@app/core/log.js';
|
||||
import { LOG_LEVEL } from '@app/environment.js';
|
||||
import { AppI18nModule } from '@app/i18n/i18n.module.js';
|
||||
import { PubSubModule } from '@app/unraid-api/app/pubsub.module.js';
|
||||
import { AuthModule } from '@app/unraid-api/auth/auth.module.js';
|
||||
import { AuthenticationGuard } from '@app/unraid-api/auth/authentication.guard.js';
|
||||
@@ -23,6 +24,7 @@ import { UnraidFileModifierModule } from '@app/unraid-api/unraid-file-modifier/u
|
||||
imports: [
|
||||
GlobalDepsModule,
|
||||
LegacyConfigModule,
|
||||
AppI18nModule,
|
||||
PubSubModule,
|
||||
ScheduleModule.forRoot(),
|
||||
LoggerModule.forRoot({
|
||||
|
||||
35
crowdin.yml
Normal file
35
crowdin.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
project_id_env: CROWDIN_PROJECT_ID
|
||||
api_token_env: CROWDIN_API_TOKEN
|
||||
base_path: .
|
||||
preserve_hierarchy: true
|
||||
|
||||
files:
|
||||
# Frontend translations
|
||||
- source: /web/src/locales/en_US.json
|
||||
translation: /web/src/locales/%locale%.json
|
||||
type: json
|
||||
update_option: update_as_unapproved
|
||||
skip_untranslated_strings: false
|
||||
export_only_approved: false
|
||||
|
||||
# Backend translations
|
||||
- source: /api/src/i18n/en/common.json
|
||||
translation: /api/src/i18n/%two_letters_code%/%file_name%.json
|
||||
type: json
|
||||
update_option: update_as_unapproved
|
||||
skip_untranslated_strings: false
|
||||
export_only_approved: false
|
||||
|
||||
- source: /api/src/i18n/en/errors.json
|
||||
translation: /api/src/i18n/%two_letters_code%/%file_name%.json
|
||||
type: json
|
||||
update_option: update_as_unapproved
|
||||
skip_untranslated_strings: false
|
||||
export_only_approved: false
|
||||
|
||||
- source: /api/src/i18n/en/validation.json
|
||||
translation: /api/src/i18n/%two_letters_code%/%file_name%.json
|
||||
type: json
|
||||
update_option: update_as_unapproved
|
||||
skip_untranslated_strings: false
|
||||
export_only_approved: false
|
||||
111
i18n-setup.md
Normal file
111
i18n-setup.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# i18n Setup Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This project uses:
|
||||
- **Frontend**: `vue-i18n` for Vue.js components
|
||||
- **Backend**: `nestjs-i18n` for NestJS API
|
||||
- **Translation Management**: Crowdin for collaborative translation
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
/web/src/locales/ # Frontend translations
|
||||
en_US.json # Base English translations
|
||||
*.json # Other locale translations
|
||||
|
||||
/api/src/i18n/ # Backend translations
|
||||
en/ # English translations
|
||||
common.json # Common messages
|
||||
errors.json # Error messages
|
||||
validation.json # Validation messages
|
||||
*/ # Other locales
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
Set these environment variables for Crowdin:
|
||||
```bash
|
||||
export CROWDIN_PROJECT_ID=your_project_id
|
||||
export CROWDIN_API_TOKEN=your_api_token
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Frontend (Vue)
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// Use translation
|
||||
const message = t('welcome')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>{{ t('hello') }}</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Backend (NestJS)
|
||||
|
||||
```typescript
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { I18nService } from 'nestjs-i18n';
|
||||
|
||||
@Injectable()
|
||||
export class MyService {
|
||||
constructor(private readonly i18n: I18nService) {}
|
||||
|
||||
async getMessage() {
|
||||
return this.i18n.translate('common.welcome');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### Extract Translation Keys
|
||||
```bash
|
||||
# Extract missing keys from Vue components
|
||||
pnpm i18n:extract
|
||||
|
||||
# Check for missing translations
|
||||
pnpm --filter ./web i18n:missing
|
||||
```
|
||||
|
||||
### Crowdin Sync
|
||||
```bash
|
||||
# Upload source files to Crowdin
|
||||
pnpm crowdin:upload
|
||||
|
||||
# Download translations from Crowdin
|
||||
pnpm crowdin:download
|
||||
|
||||
# Full sync (extract, upload, download)
|
||||
pnpm crowdin:sync
|
||||
```
|
||||
|
||||
## Build-time Integration
|
||||
|
||||
Translations are bundled at build time:
|
||||
- Frontend: Included in the Vite build process
|
||||
- Backend: Copied with the NestJS build
|
||||
|
||||
## Adding New Translations
|
||||
|
||||
1. Add key to source files (`en_US.json` or `en/*.json`)
|
||||
2. Run `pnpm crowdin:upload` to sync with Crowdin
|
||||
3. Translators work on Crowdin
|
||||
4. Run `pnpm crowdin:download` to fetch translations
|
||||
5. Build and deploy
|
||||
|
||||
## Locale Detection
|
||||
|
||||
- **Frontend**: Uses browser's Accept-Language header
|
||||
- **Backend**: Detects from (in order):
|
||||
1. Query parameter: `?lang=fr`
|
||||
2. Header: `x-locale` or `x-lang`
|
||||
3. Accept-Language header
|
||||
@@ -16,7 +16,11 @@
|
||||
"check": "manypkg check",
|
||||
"sync-webgui-repo": "node web/scripts/sync-webgui-repo.js",
|
||||
"preinstall": "npx check-node-version --node 22 || echo '❌ Node.js 22 required. See readme.md Prerequisites section.'",
|
||||
"postinstall": "simple-git-hooks"
|
||||
"postinstall": "simple-git-hooks",
|
||||
"i18n:extract": "pnpm --filter ./web i18n:extract",
|
||||
"crowdin:upload": "crowdin upload sources",
|
||||
"crowdin:download": "crowdin download",
|
||||
"crowdin:sync": "pnpm i18n:extract && crowdin upload sources && crowdin download"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
@@ -56,6 +60,7 @@
|
||||
"ignore": "7.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@crowdin/cli": "^4.11.0",
|
||||
"lint-staged": "16.1.5",
|
||||
"simple-git-hooks": "2.13.1"
|
||||
},
|
||||
|
||||
177
pnpm-lock.yaml
generated
177
pnpm-lock.yaml
generated
@@ -25,6 +25,9 @@ importers:
|
||||
specifier: 7.0.5
|
||||
version: 7.0.5
|
||||
devDependencies:
|
||||
'@crowdin/cli':
|
||||
specifier: ^4.11.0
|
||||
version: 4.11.0
|
||||
lint-staged:
|
||||
specifier: 16.1.5
|
||||
version: 16.1.5
|
||||
@@ -223,6 +226,9 @@ importers:
|
||||
graphql-ws:
|
||||
specifier: 6.0.6
|
||||
version: 6.0.6(crossws@0.3.5)(graphql@16.11.0)(ws@8.18.3)
|
||||
i18next:
|
||||
specifier: ^25.5.2
|
||||
version: 25.5.2(typescript@5.9.2)
|
||||
ini:
|
||||
specifier: 5.0.0
|
||||
version: 5.0.0
|
||||
@@ -250,6 +256,9 @@ importers:
|
||||
nest-commander:
|
||||
specifier: 3.19.0
|
||||
version: 3.19.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(reflect-metadata@0.1.14)(rxjs@7.8.2))(@types/inquirer@9.0.9)(@types/node@22.18.0)(typescript@5.9.2)
|
||||
nestjs-i18n:
|
||||
specifier: ^10.5.1
|
||||
version: 10.5.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(reflect-metadata@0.1.14)(rxjs@7.8.2))(class-validator@0.14.2)(rxjs@7.8.2)
|
||||
nestjs-pino:
|
||||
specifier: 4.4.0
|
||||
version: 4.4.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(pino-http@10.5.0)(pino@9.9.0)(rxjs@7.8.2)
|
||||
@@ -1311,6 +1320,9 @@ importers:
|
||||
vue-eslint-parser:
|
||||
specifier: 10.2.0
|
||||
version: 10.2.0(eslint@9.34.0(jiti@2.5.1))
|
||||
vue-i18n-extract:
|
||||
specifier: github:Spittal/vue-i18n-extract
|
||||
version: https://codeload.github.com/Spittal/vue-i18n-extract/tar.gz/f856484d2f62abbd931d84676519f529062d94da
|
||||
vue-tsc:
|
||||
specifier: 3.0.6
|
||||
version: 3.0.6(typescript@5.9.2)
|
||||
@@ -1901,6 +1913,10 @@ packages:
|
||||
conventional-commits-parser:
|
||||
optional: true
|
||||
|
||||
'@crowdin/cli@4.11.0':
|
||||
resolution: {integrity: sha512-oIOzCHCc9eHOqcQw1bjcnfFUoJDFVobCN5MEZ1rwjYOhPMpIcRNBDnUT/b43LcRWsogU3c0BwcWN/BHvV19DWg==}
|
||||
hasBin: true
|
||||
|
||||
'@cspotcode/source-map-support@0.8.1':
|
||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -4969,6 +4985,9 @@ packages:
|
||||
abstract-logging@2.0.1:
|
||||
resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==}
|
||||
|
||||
accept-language-parser@1.5.0:
|
||||
resolution: {integrity: sha512-QhyTbMLYo0BBGg1aWbeMG4ekWtds/31BrEU+DONOg/7ax23vxpL03Pb7/zBmha2v7vdD3AyzZVWBVGEZxKOXWw==}
|
||||
|
||||
accepts@1.3.8:
|
||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@@ -5371,6 +5390,9 @@ packages:
|
||||
bser@2.1.1:
|
||||
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
||||
|
||||
buffer-crc32@0.2.13:
|
||||
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
|
||||
|
||||
buffer-from@1.1.2:
|
||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||
|
||||
@@ -5656,6 +5678,10 @@ packages:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
command-exists-promise@2.0.2:
|
||||
resolution: {integrity: sha512-T6PB6vdFrwnHXg/I0kivM3DqaCGZLjjYSOe0a5WgFKcz1sOnmOeIjnhQPXVXX3QjVbLyTJ85lJkX6lUpukTzaA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
command-exists@1.2.9:
|
||||
resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==}
|
||||
|
||||
@@ -5681,6 +5707,10 @@ packages:
|
||||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
commander@6.2.1:
|
||||
resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
commander@9.5.0:
|
||||
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
|
||||
engines: {node: ^12.20.0 || >=14}
|
||||
@@ -6229,6 +6259,10 @@ packages:
|
||||
dot-case@3.0.4:
|
||||
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
|
||||
|
||||
dot-object@2.1.5:
|
||||
resolution: {integrity: sha512-xHF8EP4XH/Ba9fvAF2LDd5O3IITVolerVV6xvkxoM8zlGEiCUrggpAnHyOoKJKCrhvPcGATFAUwIujj7bRG5UA==}
|
||||
hasBin: true
|
||||
|
||||
dot-prop@5.3.0:
|
||||
resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -7229,6 +7263,11 @@ packages:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
glob@8.1.0:
|
||||
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
|
||||
engines: {node: '>=12'}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
global-agent@3.0.0:
|
||||
resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
|
||||
engines: {node: '>=10.0'}
|
||||
@@ -7503,6 +7542,14 @@ packages:
|
||||
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
i18next@25.5.2:
|
||||
resolution: {integrity: sha512-lW8Zeh37i/o0zVr+NoCHfNnfvVw+M6FQbRp36ZZ/NyHDJ3NJVpp2HhAUyU9WafL5AssymNoOjMRB48mmx2P6Hw==}
|
||||
peerDependencies:
|
||||
typescript: ^5
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -7603,6 +7650,10 @@ packages:
|
||||
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
interpret@1.4.0:
|
||||
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
invariant@2.2.4:
|
||||
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
|
||||
|
||||
@@ -7849,6 +7900,10 @@ packages:
|
||||
is-utf8@0.2.1:
|
||||
resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==}
|
||||
|
||||
is-valid-glob@1.0.0:
|
||||
resolution: {integrity: sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
is-weakmap@2.0.2:
|
||||
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -8493,6 +8548,10 @@ packages:
|
||||
minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
|
||||
minimatch@5.1.6:
|
||||
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
minimatch@7.4.6:
|
||||
resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -8646,6 +8705,15 @@ packages:
|
||||
'@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
'@types/inquirer': ^8.1.3
|
||||
|
||||
nestjs-i18n@10.5.1:
|
||||
resolution: {integrity: sha512-cJJFz+RUfav23QACpGCq1pdXNLYC3tBesrP14RGoE/YYcD4xosQPX2eyjvDNuo0Ti63Xtn6j57wDNEUKrZqmSw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@nestjs/common': '*'
|
||||
'@nestjs/core': '*'
|
||||
class-validator: '*'
|
||||
rxjs: '*'
|
||||
|
||||
nestjs-pino@4.4.0:
|
||||
resolution: {integrity: sha512-+GMNlcNWDRrMtlQftfcxN+5pV2C25A4wsYIY7cfRJTMW4b8IFKYReDrG1lUp5LGql9fXemmnVJ2Ww10iIkCZPQ==}
|
||||
engines: {node: '>= 14'}
|
||||
@@ -9099,6 +9167,9 @@ packages:
|
||||
pause@0.0.1:
|
||||
resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==}
|
||||
|
||||
pend@1.2.0:
|
||||
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
|
||||
|
||||
perfect-debounce@1.0.0:
|
||||
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
|
||||
|
||||
@@ -9524,6 +9595,10 @@ packages:
|
||||
resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
rechoir@0.6.2:
|
||||
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
redent@3.0.0:
|
||||
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -9872,6 +9947,11 @@ packages:
|
||||
resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
shelljs@0.8.5:
|
||||
resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
shimmer@1.2.1:
|
||||
resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==}
|
||||
|
||||
@@ -10071,6 +10151,9 @@ packages:
|
||||
string-env-interpolation@1.0.1:
|
||||
resolution: {integrity: sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==}
|
||||
|
||||
string-format@2.0.0:
|
||||
resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==}
|
||||
|
||||
string-width@3.1.0:
|
||||
resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -11017,6 +11100,11 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
|
||||
vue-i18n-extract@https://codeload.github.com/Spittal/vue-i18n-extract/tar.gz/f856484d2f62abbd931d84676519f529062d94da:
|
||||
resolution: {tarball: https://codeload.github.com/Spittal/vue-i18n-extract/tar.gz/f856484d2f62abbd931d84676519f529062d94da}
|
||||
version: 2.0.8
|
||||
hasBin: true
|
||||
|
||||
vue-i18n@11.1.11:
|
||||
resolution: {integrity: sha512-LvyteQoXeQiuILbzqv13LbyBna/TEv2Ha+4ZWK2AwGHUzZ8+IBaZS0TJkCgn5izSPLcgZwXy9yyTrewCb2u/MA==}
|
||||
engines: {node: '>= 16'}
|
||||
@@ -11352,6 +11440,10 @@ packages:
|
||||
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yauzl@3.2.0:
|
||||
resolution: {integrity: sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
yocto-queue@0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -12169,6 +12261,16 @@ snapshots:
|
||||
conventional-commits-filter: 5.0.0
|
||||
conventional-commits-parser: 6.0.0
|
||||
|
||||
'@crowdin/cli@4.11.0':
|
||||
dependencies:
|
||||
command-exists-promise: 2.0.2
|
||||
node-fetch: 2.7.0
|
||||
shelljs: 0.8.5
|
||||
tar: 7.4.3
|
||||
yauzl: 3.2.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
'@cspotcode/source-map-support@0.8.1':
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.9
|
||||
@@ -15692,6 +15794,8 @@ snapshots:
|
||||
|
||||
abstract-logging@2.0.1: {}
|
||||
|
||||
accept-language-parser@1.5.0: {}
|
||||
|
||||
accepts@1.3.8:
|
||||
dependencies:
|
||||
mime-types: 2.1.35
|
||||
@@ -16114,6 +16218,8 @@ snapshots:
|
||||
dependencies:
|
||||
node-int64: 0.4.0
|
||||
|
||||
buffer-crc32@0.2.13: {}
|
||||
|
||||
buffer-from@1.1.2: {}
|
||||
|
||||
buffer@5.7.1:
|
||||
@@ -16456,6 +16562,8 @@ snapshots:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
command-exists-promise@2.0.2: {}
|
||||
|
||||
command-exists@1.2.9: {}
|
||||
|
||||
commander@10.0.1: {}
|
||||
@@ -16470,6 +16578,8 @@ snapshots:
|
||||
|
||||
commander@2.20.3: {}
|
||||
|
||||
commander@6.2.1: {}
|
||||
|
||||
commander@9.5.0:
|
||||
optional: true
|
||||
|
||||
@@ -16998,6 +17108,11 @@ snapshots:
|
||||
no-case: 3.0.4
|
||||
tslib: 2.8.1
|
||||
|
||||
dot-object@2.1.5:
|
||||
dependencies:
|
||||
commander: 6.2.1
|
||||
glob: 7.2.3
|
||||
|
||||
dot-prop@5.3.0:
|
||||
dependencies:
|
||||
is-obj: 2.0.0
|
||||
@@ -18232,6 +18347,14 @@ snapshots:
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
|
||||
glob@8.1.0:
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 5.1.6
|
||||
once: 1.4.0
|
||||
|
||||
global-agent@3.0.0:
|
||||
dependencies:
|
||||
boolean: 3.2.0
|
||||
@@ -18520,6 +18643,12 @@ snapshots:
|
||||
|
||||
human-signals@8.0.1: {}
|
||||
|
||||
i18next@25.5.2(typescript@5.9.2):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
optionalDependencies:
|
||||
typescript: 5.9.2
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
@@ -18644,6 +18773,8 @@ snapshots:
|
||||
hasown: 2.0.2
|
||||
side-channel: 1.1.0
|
||||
|
||||
interpret@1.4.0: {}
|
||||
|
||||
invariant@2.2.4:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
@@ -18867,6 +18998,8 @@ snapshots:
|
||||
|
||||
is-utf8@0.2.1: {}
|
||||
|
||||
is-valid-glob@1.0.0: {}
|
||||
|
||||
is-weakmap@2.0.2: {}
|
||||
|
||||
is-weakref@1.1.1:
|
||||
@@ -19468,6 +19601,10 @@ snapshots:
|
||||
dependencies:
|
||||
brace-expansion: 1.1.12
|
||||
|
||||
minimatch@5.1.6:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
|
||||
minimatch@7.4.6:
|
||||
dependencies:
|
||||
brace-expansion: 2.0.2
|
||||
@@ -19599,6 +19736,19 @@ snapshots:
|
||||
- '@types/node'
|
||||
- typescript
|
||||
|
||||
nestjs-i18n@10.5.1(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/core@11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(reflect-metadata@0.1.14)(rxjs@7.8.2))(class-validator@0.14.2)(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
'@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
accept-language-parser: 1.5.0
|
||||
chokidar: 3.6.0
|
||||
class-validator: 0.14.2
|
||||
cookie: 0.7.1
|
||||
iterare: 1.2.1
|
||||
js-yaml: 4.1.0
|
||||
rxjs: 7.8.2
|
||||
string-format: 2.0.0
|
||||
|
||||
nestjs-pino@4.4.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2))(pino-http@10.5.0)(pino@9.9.0)(rxjs@7.8.2):
|
||||
dependencies:
|
||||
'@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.1.14)(rxjs@7.8.2)
|
||||
@@ -20088,6 +20238,8 @@ snapshots:
|
||||
|
||||
pause@0.0.1: {}
|
||||
|
||||
pend@1.2.0: {}
|
||||
|
||||
perfect-debounce@1.0.0: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
@@ -20590,6 +20742,10 @@ snapshots:
|
||||
tiny-invariant: 1.3.3
|
||||
tslib: 2.8.1
|
||||
|
||||
rechoir@0.6.2:
|
||||
dependencies:
|
||||
resolve: 1.22.10
|
||||
|
||||
redent@3.0.0:
|
||||
dependencies:
|
||||
indent-string: 4.0.0
|
||||
@@ -21034,6 +21190,12 @@ snapshots:
|
||||
|
||||
shell-quote@1.8.3: {}
|
||||
|
||||
shelljs@0.8.5:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
interpret: 1.4.0
|
||||
rechoir: 0.6.2
|
||||
|
||||
shimmer@1.2.1: {}
|
||||
|
||||
side-channel-list@1.0.0:
|
||||
@@ -21244,6 +21406,8 @@ snapshots:
|
||||
|
||||
string-env-interpolation@1.0.1: {}
|
||||
|
||||
string-format@2.0.0: {}
|
||||
|
||||
string-width@3.1.0:
|
||||
dependencies:
|
||||
emoji-regex: 7.0.3
|
||||
@@ -22275,6 +22439,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vue-i18n-extract@https://codeload.github.com/Spittal/vue-i18n-extract/tar.gz/f856484d2f62abbd931d84676519f529062d94da:
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
dot-object: 2.1.5
|
||||
glob: 8.1.0
|
||||
is-valid-glob: 1.0.0
|
||||
js-yaml: 4.1.0
|
||||
|
||||
vue-i18n@11.1.11(vue@3.5.20(typescript@5.9.2)):
|
||||
dependencies:
|
||||
'@intlify/core-base': 11.1.11
|
||||
@@ -22630,6 +22802,11 @@ snapshots:
|
||||
y18n: 5.0.8
|
||||
yargs-parser: 21.1.1
|
||||
|
||||
yauzl@3.2.0:
|
||||
dependencies:
|
||||
buffer-crc32: 0.2.13
|
||||
pend: 1.2.0
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
yocto-queue@1.2.1: {}
|
||||
|
||||
@@ -34,7 +34,10 @@
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:ci": "vitest run",
|
||||
"test:standalone": "pnpm run build && vite --config vite.test.config.ts"
|
||||
"test:standalone": "pnpm run build && vite --config vite.test.config.ts",
|
||||
"// i18n": "",
|
||||
"i18n:extract": "vue-i18n-extract report --vueFiles './src/**/*.{vue,ts,js}' --languageFiles './src/locales/*.json'",
|
||||
"i18n:missing": "vue-i18n-extract report --vueFiles './src/**/*.{vue,ts,js}' --languageFiles './src/locales/*.json' --output missing.json && cat missing.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.34.0",
|
||||
@@ -84,6 +87,7 @@
|
||||
"vitest": "3.2.4",
|
||||
"vue": "3.5.20",
|
||||
"vue-eslint-parser": "10.2.0",
|
||||
"vue-i18n-extract": "github:Spittal/vue-i18n-extract",
|
||||
"vue-tsc": "3.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
Reference in New Issue
Block a user