mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-09-10 22:14:48 -05:00
feat(web-stack): add new i18n guidelines + ESLint + update and fixes (#7753)
- Add new i18n guidelines
- Remove nested keys: `"foo": { "bar": "..." }` ➡️ `"foo.bar": "..."`
This makes code cleaner (and as a side-effect, it now allows to use `foo` + `foo.bar` keys)
- Lite/6 shared translations are no longer prefixed with `core.`
- Duplicated keys across translation files are no longer accepted.
This will prevent accidental overwrite of missing common translations
- `fr.json` and `en.json` now required to contains the same keys
- Raw text is no longer accepted in template to prevent forgetting a translation
Raw text is still accepted in dev-related files (stories, dev pages...)
- Remove useless `alt` on `img`
- Display of percentage now uses `$n(value, 'percent')`
- Removed legacy `lite/src/i18n.ts`
- Add missing translations
- Added visual indicator for missing translations while in dev env: `🌎❗⟨i-am-missing⟩`
This commit is contained in:
committed by
GitHub
parent
dd8ad3f274
commit
276d920cca
53
.eslintrc.js
53
.eslintrc.js
@@ -177,6 +177,59 @@ module.exports = {
|
||||
'vue/valid-define-options': 'error',
|
||||
},
|
||||
},
|
||||
// Specific rules for XO i18n-related files
|
||||
{
|
||||
files: [
|
||||
'@xen-orchestra/lite/**/*.{vue,ts,json}',
|
||||
'@xen-orchestra/web/**/*.{vue,ts,json}',
|
||||
'@xen-orchestra/web-core/**/*.{vue,ts,json}',
|
||||
],
|
||||
extends: ['plugin:@intlify/vue-i18n/base'],
|
||||
settings: {
|
||||
'vue-i18n': {
|
||||
localeDir: [
|
||||
'@xen-orchestra/lite/src/locales/*.json',
|
||||
'@xen-orchestra/web/src/locales/*.json',
|
||||
'@xen-orchestra/web-core/lib/locales/*.json',
|
||||
],
|
||||
messageSyntaxVersion: '^9.9.0',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
strict: 'off',
|
||||
'no-irregular-whitespace': 'off',
|
||||
'@intlify/vue-i18n/no-deprecated-i18n-component': 'error',
|
||||
'@intlify/vue-i18n/no-deprecated-i18n-place-attr': 'error',
|
||||
'@intlify/vue-i18n/no-deprecated-i18n-places-prop': 'error',
|
||||
'@intlify/vue-i18n/no-deprecated-modulo-syntax': 'error',
|
||||
'@intlify/vue-i18n/no-deprecated-tc': 'error',
|
||||
'@intlify/vue-i18n/no-html-messages': 'error',
|
||||
'@intlify/vue-i18n/no-i18n-t-path-prop': 'error',
|
||||
'@intlify/vue-i18n/no-missing-keys': 'error',
|
||||
'@intlify/vue-i18n/no-raw-text': [
|
||||
'error',
|
||||
{
|
||||
ignoreText: ['Xen Orchestra Lite', 'Xen Orchestra', 'XO Lite', 'XCP-ng', 'XO 5', '404', '⚠️'],
|
||||
},
|
||||
],
|
||||
'@intlify/vue-i18n/no-v-html': 'error',
|
||||
'@intlify/vue-i18n/valid-message-syntax': 'error',
|
||||
'@intlify/vue-i18n/no-duplicate-keys-in-locale': 'error',
|
||||
'@intlify/vue-i18n/no-missing-keys-in-other-locales': ['error', { ignoreLocales: ['de'] }],
|
||||
},
|
||||
},
|
||||
// Specific rules for XO dev-related files
|
||||
{
|
||||
files: [
|
||||
'@xen-orchestra/lite/src/stories/**/*',
|
||||
'@xen-orchestra/lite/src/components/component-story/**/*',
|
||||
'@xen-orchestra/web/src/pages/dev/**/*',
|
||||
'@xen-orchestra/lite/src/views/story/**/*',
|
||||
],
|
||||
rules: {
|
||||
'@intlify/vue-i18n/no-raw-text': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['@xen-orchestra/{web-core,lite,web}/src/pages/**/*.vue'],
|
||||
parserOptions: {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{{ $t('send-us-feedback') }}
|
||||
</MenuItem>
|
||||
<MenuItem :icon="faArrowRightFromBracket" class="menu-item-logout" @click="logout">
|
||||
{{ $t('core.log-out') }}
|
||||
{{ $t('log-out') }}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</template>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<template v-else>
|
||||
<FormWidget :before="currentFilterIcon">
|
||||
<select v-model="newFilter.builder.property">
|
||||
<option v-if="!newFilter.builder.property" value="">- {{ $t('property') }} -</option>
|
||||
<option v-if="!newFilter.builder.property" value="">{{ `- ${$t('property')} -` }}</option>
|
||||
<option v-for="(filter, property) in availableFilters" :key="property" :value="property">
|
||||
{{ filter.label ?? property }}
|
||||
</option>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="no-data">
|
||||
<img alt="No data" class="img" src="@/assets/undraw-bug-fixing.svg" />
|
||||
<img alt="" class="img" src="@/assets/undraw-bug-fixing.svg" />
|
||||
<p class="text-error typo h4-medium">{{ $t('error-no-data') }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{{ $t('here') }} →
|
||||
{{ `${$t('here')} →` }}
|
||||
</a>
|
||||
</p>
|
||||
</UiStatusPanel>
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
class="progress-circle-fill"
|
||||
d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
|
||||
/>
|
||||
<text class="progress-circle-text" text-anchor="middle" x="50%" y="50%">{{ progress }}%</text>
|
||||
<text class="progress-circle-text" text-anchor="middle" x="50%" y="50%">
|
||||
{{ $n(progress / 100, 'percent') }}
|
||||
</text>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
class="progress-item"
|
||||
>
|
||||
<UiProgressBar :value="item.value" color="custom" />
|
||||
<UiProgressLegend :label="item.label" :value="item.badgeLabel ?? `${item.value}%`" />
|
||||
<UiProgressLegend :label="item.label" :value="item.badgeLabel ?? $n(item.value / 100, 'percent')" />
|
||||
</div>
|
||||
<slot :total-percent="computedData.totalPercentUsage" name="footer" />
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<FormInputGroup>
|
||||
<FormNumber v-model="sizeInput" :max-decimals="3" />
|
||||
<FormSelect v-model="prefixInput">
|
||||
<option v-for="currentPrefix in availablePrefixes" :key="currentPrefix" :value="currentPrefix">
|
||||
{{ currentPrefix }}B
|
||||
</option>
|
||||
<option value="Ki">{{ $t('bytes.ki') }}</option>
|
||||
<option value="Mi">{{ $t('bytes.mi') }}</option>
|
||||
<option value="Gi">{{ $t('bytes.gi') }}</option>
|
||||
</FormSelect>
|
||||
</FormInputGroup>
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TreeItemLabel :icon="faServer" :route="{ name: 'host.dashboard', params: { uuid: host.uuid } }">
|
||||
{{ host.name_label || '(Host)' }}
|
||||
<template #addons>
|
||||
<UiIcon v-if="isPoolMaster" v-tooltip="$t('core.master')" :icon="faStar" color="warning" />
|
||||
<UiIcon v-if="isPoolMaster" v-tooltip="$t('master')" :icon="faStar" color="warning" />
|
||||
<UiCounter v-if="isReady" v-tooltip="$t('vm-running', { count: vmCount })" :value="vmCount" color="info" />
|
||||
</template>
|
||||
</TreeItemLabel>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div v-else-if="isReady" :class="state" class="progress-item">
|
||||
<UiProgressBar :max-value="maxValue" :value color="custom" />
|
||||
<UiProgressScale :max-value="maxValue" :steps="1" unit="%" />
|
||||
<UiProgressLegend :label="$t('vcpus')" :value="`${value}%`" />
|
||||
<UiProgressLegend :label="$t('vcpus')" :value="$n(value / 100, 'percent')" />
|
||||
<UiCardFooter class="ui-card-footer">
|
||||
<template #left>
|
||||
<p>{{ $t('vcpus-used') }}</p>
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
{{ $t(`alarm-type.${alarm.type}`, { n: alarm.triggerLevel * 100 }) }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="level typo h7-semi-bold">{{ alarm.level * 100 }}%</td>
|
||||
<td class="level typo h7-semi-bold">
|
||||
<!-- Using `Math.min` because `alarm.level` can be `Infinity` -->
|
||||
{{ $n(Math.min(alarm.level, 1), 'percent') }}
|
||||
</td>
|
||||
<td class="on">{{ $t('on-object', { object: alarm.cls }) }}</td>
|
||||
<td class="object">
|
||||
<ObjectLink :type="rawTypeToType(alarm.cls)" :uuid="alarm.obj_uuid" />
|
||||
|
||||
@@ -27,7 +27,7 @@ import { useI18n } from 'vue-i18n'
|
||||
|
||||
const LinearChart = defineAsyncComponent(() => import('@/components/charts/LinearChart.vue'))
|
||||
|
||||
const { t } = useI18n()
|
||||
const { t, n } = useI18n()
|
||||
|
||||
const hostLastWeekStats = inject(IK_HOST_LAST_WEEK_STATS)
|
||||
|
||||
@@ -88,5 +88,5 @@ const isStatFetched = computed(() => {
|
||||
|
||||
const isLoading = computed(() => isFetching.value || !isStatFetched.value)
|
||||
|
||||
const customValueFormatter: ValueFormatter = value => `${value}%`
|
||||
const customValueFormatter: ValueFormatter = value => n(value / 100, 'percent')
|
||||
</script>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div v-if="isDisplayed" class="summary typo c2-semi-bold">
|
||||
<div class="summary-card">
|
||||
<p>{{ $t('total-used') }}:</p>
|
||||
<p>{{ $t('total-used:') }}</p>
|
||||
<div class="summary-value">
|
||||
<p>{{ percentUsed }}%</p>
|
||||
<p>{{ $n(percentUsed / 100, 'percent') }}</p>
|
||||
<p>
|
||||
{{ formatSize(usage) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p>{{ $t('total-free') }}:</p>
|
||||
<p>{{ $t('total-free:') }}</p>
|
||||
<div class="summary-value">
|
||||
<p>{{ percentFree }}%</p>
|
||||
<p>{{ $n(percentFree / 100, 'percent') }}</p>
|
||||
<p>
|
||||
{{ formatSize(free) }}
|
||||
</p>
|
||||
|
||||
@@ -17,7 +17,7 @@ const props = withDefaults(
|
||||
{ color: 'info', maxValue: 100 }
|
||||
)
|
||||
|
||||
const progressWithUnit = computed(() => {
|
||||
const cssFillWidth = computed(() => {
|
||||
const progress = (props.value / props.maxValue) * 100
|
||||
return `${progress}%`
|
||||
})
|
||||
@@ -49,7 +49,7 @@ const progressWithUnit = computed(() => {
|
||||
}
|
||||
|
||||
.fill {
|
||||
width: v-bind(progressWithUnit);
|
||||
width: v-bind(cssFillWidth);
|
||||
height: var(--progress-bar-height, 0.4rem);
|
||||
transition: width 1s ease-in-out;
|
||||
background-color: var(--progress-bar-color);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<p class="unit typo p3-regular">
|
||||
<span>0{{ unit }}</span>
|
||||
<span>{{ `0${unit}` }}</span>
|
||||
<span v-for="step in steps" :key="step"> {{ Math.round((maxValue / (steps + 1)) * step) }}{{ unit }} </span>
|
||||
<span>{{ maxValue }}{{ unit }}</span>
|
||||
</p>
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
import messages from '@intlify/unplugin-vue-i18n/messages'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
|
||||
interface Locales {
|
||||
[key: string]: {
|
||||
code: string
|
||||
name: string
|
||||
}
|
||||
}
|
||||
|
||||
export const locales: Locales = {
|
||||
en: {
|
||||
code: 'en',
|
||||
name: 'English',
|
||||
},
|
||||
fr: {
|
||||
code: 'fr',
|
||||
name: 'Français',
|
||||
},
|
||||
de: {
|
||||
code: 'de',
|
||||
name: 'Deutsch',
|
||||
},
|
||||
}
|
||||
|
||||
export default createI18n({
|
||||
locale: localStorage.getItem('lang') ?? 'en',
|
||||
fallbackLocale: 'en',
|
||||
messages,
|
||||
datetimeFormats: {
|
||||
en: {
|
||||
date_short: {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
},
|
||||
date_medium: {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
},
|
||||
date_long: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
},
|
||||
datetime_short: {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
datetime_medium: {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
datetime_long: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
time: {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
},
|
||||
fr: {
|
||||
date_short: {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
},
|
||||
date_medium: {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
},
|
||||
date_long: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
},
|
||||
datetime_short: {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
datetime_medium: {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
datetime_long: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
time: {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
},
|
||||
de: {
|
||||
date_short: {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
},
|
||||
date_medium: {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
},
|
||||
date_long: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
},
|
||||
datetime_short: {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
datetime_medium: {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
datetime_long: {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
time: {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -8,19 +8,18 @@
|
||||
"admin-login": "Administrator Login",
|
||||
"admin-password": "Administrator Passwort",
|
||||
"admin-password-confirm": "Administrator Passwortbestätigung",
|
||||
"alarm-type": {
|
||||
"cpu_usage": "CPU-Nutzung überschreitet {n}%",
|
||||
"disk_usage": "Speicherbelegung überschreitet {n}%",
|
||||
"fs_usage": "Dateisystem überschreitet {n}%",
|
||||
"log_fs_usage": "Loggingdateisystem überschreitet {n}%",
|
||||
"mem_usage": "Arbeitsspeicherauslastung überschreitet {n}%",
|
||||
"memory_free_kib": "Freier Speicher fällt unter {n}%",
|
||||
"network_usage": "Netzwerkauslastung überschreitet {n}%",
|
||||
"physical_utilisation": "Physical utilisation exceeds {n}%",
|
||||
"sr_io_throughput_total_per_host": "SR IO throughput total per host exceeds {n}%",
|
||||
"unknown": "unbekannter Alarmtyp"
|
||||
},
|
||||
"alarms": "Alarme",
|
||||
|
||||
"alarm-type.cpu_usage": "CPU-Nutzung überschreitet {n}%",
|
||||
"alarm-type.disk_usage": "Speicherbelegung überschreitet {n}%",
|
||||
"alarm-type.fs_usage": "Dateisystem überschreitet {n}%",
|
||||
"alarm-type.log_fs_usage": "Loggingdateisystem überschreitet {n}%",
|
||||
"alarm-type.mem_usage": "Arbeitsspeicherauslastung überschreitet {n}%",
|
||||
"alarm-type.memory_free_kib": "Freier Speicher fällt unter {n}%",
|
||||
"alarm-type.network_usage": "Netzwerkauslastung überschreitet {n}%",
|
||||
"alarm-type.physical_utilisation": "Physical utilisation exceeds {n}%",
|
||||
"alarm-type.sr_io_throughput_total_per_host": "SR IO throughput total per host exceeds {n}%",
|
||||
"alarm-type.unknown": "unbekannter Alarmtyp",
|
||||
|
||||
"all-good": "Alles in Ordnung!",
|
||||
"allow-self-signed-ssl": "Es müssen eventuell selbstsignierte SSL-Zertifikate im Browser zugelassen werden",
|
||||
"appearance": "Aussehen",
|
||||
@@ -33,32 +32,29 @@
|
||||
"check-errors": "Überprüfe die Fehler:",
|
||||
"click-to-display-alarms": "Hier klicken um Alarme anzuzeigen:",
|
||||
"click-to-return-default-pool": "Hier klicken um zum Standardpool zurückzukehren",
|
||||
"coming-soon": "Bald verfügbar!",
|
||||
"community": "Community",
|
||||
"community-name": "{name} community",
|
||||
"configuration": "Konfiguration",
|
||||
"confirm-cancel": "Willst du wirklich abbrechen?",
|
||||
"confirm-delete": "Willst du wirklich {0} löschen?",
|
||||
"console": "Konsole",
|
||||
"console-unavailable": "Die Konsole ist nicht verfügbar",
|
||||
"copy": "Kopieren",
|
||||
"cpu-provisioning": "Zugewiesene Prozessoren",
|
||||
"cpu-provisioning-warning": "Die Anzahl der zugewiesenen vCPUs überschreitet die physikalisch vorhandenen CPUs. Die Systemperformance kann darunter leiden.",
|
||||
"cpu-usage": "Prozessorauslastung",
|
||||
"dashboard": "Dashboard",
|
||||
"delete": "Löschen",
|
||||
"delete-vms": "1 VM löschen| {n} VMs löschen",
|
||||
"deploy": "Installieren",
|
||||
"deploy-xoa": "XOA installieren",
|
||||
"deploy-xoa-available-on-desktop": "Die Installation von XOA ist auf dem Desktop verfügbar",
|
||||
"deploy-xoa-status": {
|
||||
"configuring": "Konfiguriere XOA…",
|
||||
"importing": "Importiere XOA…",
|
||||
"not-responding": "XOA antwortet nicht",
|
||||
"ready": "XOA ist startklar!",
|
||||
"starting": "Starte XOA…",
|
||||
"waiting": "Warte auf Antwort von XOA…"
|
||||
},
|
||||
|
||||
"deploy-xoa-status.configuring": "Konfiguriere XOA…",
|
||||
"deploy-xoa-status.importing": "Importiere XOA…",
|
||||
"deploy-xoa-status.not-responding": "XOA antwortet nicht",
|
||||
"deploy-xoa-status.ready": "XOA ist startklar!",
|
||||
"deploy-xoa-status.starting": "Starte XOA…",
|
||||
"deploy-xoa-status.waiting": "Warte auf Antwort von XOA…",
|
||||
|
||||
"descending": "absteigend",
|
||||
"description": "Beschreibung",
|
||||
"dhcp": "DHCP",
|
||||
@@ -67,7 +63,6 @@
|
||||
"dns": "DNS",
|
||||
"do-you-have-needs": "Vermisst du Funktionen oder hast Vorschläge? Sag uns Bescheid: ",
|
||||
"documentation": "Dokumentation",
|
||||
"documentation-name": "{name} Dokumentation",
|
||||
"edit-config": "Einstellungen anpassen",
|
||||
"enabled": "Aktiviert",
|
||||
"error-no-data": "Fehler beim Datenabruf.",
|
||||
@@ -80,24 +75,22 @@
|
||||
"export-vms": "VMs exportieren",
|
||||
"export-vms-manually-information": "Some VM exports were not able to start automatically, probably due to your browser settings. To export them, you should click on each one. (Alternatively, copy the link as well.)",
|
||||
"fetching-fresh-data": "Rufe neue Daten ab",
|
||||
"filter": {
|
||||
"comparison": {
|
||||
"contains": "Enthält",
|
||||
"ends-with": "Endet mit",
|
||||
"equals": "Entspricht",
|
||||
"is": "Ist",
|
||||
"is-false": "Ist falsch",
|
||||
"is-not": "Ist nicht",
|
||||
"is-true": "Ist wahr",
|
||||
"matches-regex": "Entspricht Regulärem Ausdruck",
|
||||
"not-contain": "Enthält nicht",
|
||||
"not-end-with": "Endet nicht mit",
|
||||
"not-equal": "Entspricht nicht",
|
||||
"not-match-regex": "Entspricht nicht Regulärem Ausdruck",
|
||||
"not-start-with": "Beginnt nicht mit",
|
||||
"starts-with": "Beginnt mit"
|
||||
}
|
||||
},
|
||||
|
||||
"filter.comparison.contains": "Enthält",
|
||||
"filter.comparison.ends-with": "Endet mit",
|
||||
"filter.comparison.equals": "Entspricht",
|
||||
"filter.comparison.is": "Ist",
|
||||
"filter.comparison.is-false": "Ist falsch",
|
||||
"filter.comparison.is-not": "Ist nicht",
|
||||
"filter.comparison.is-true": "Ist wahr",
|
||||
"filter.comparison.matches-regex": "Entspricht Regulärem Ausdruck",
|
||||
"filter.comparison.not-contain": "Enthält nicht",
|
||||
"filter.comparison.not-end-with": "Endet nicht mit",
|
||||
"filter.comparison.not-equal": "Entspricht nicht",
|
||||
"filter.comparison.not-match-regex": "Entspricht nicht Regulärem Ausdruck",
|
||||
"filter.comparison.not-start-with": "Beginnt nicht mit",
|
||||
"filter.comparison.starts-with": "Beginnt mit",
|
||||
|
||||
"following-hosts-unreachable": "Die folgenden Hosts sind nicht erreichbar",
|
||||
"force-reboot": "Neustart erzwingen",
|
||||
"force-shutdown": "Herunterfahren erzwingen",
|
||||
@@ -109,10 +102,10 @@
|
||||
"go-back": "Zurück",
|
||||
"gzip": "gzip",
|
||||
"here": "Hier",
|
||||
"host": {
|
||||
"active": "Aktiv",
|
||||
"inactive": "Inaktiv"
|
||||
},
|
||||
|
||||
"host.active": "Aktiv",
|
||||
"host.inactive": "Inaktiv",
|
||||
|
||||
"hosts": "Hosts",
|
||||
"invalid-field": "Ungültiges Feld",
|
||||
"keep-me-logged": "Angemeldet bleiben",
|
||||
@@ -132,7 +125,6 @@
|
||||
"n-vms": "1 VM | {n} VMs",
|
||||
"name": "Name",
|
||||
"netmask": "Netzmaske",
|
||||
"network": "Netzwerk",
|
||||
"network-download": "Download",
|
||||
"network-throughput": "Netzwerkdurchsatz",
|
||||
"network-upload": "Upload",
|
||||
@@ -159,23 +151,22 @@
|
||||
"please-confirm": "Bitte bestätigen",
|
||||
"pool-cpu-usage": "Pool Prozessorauslastung",
|
||||
"pool-ram-usage": "Pool Arbeitsspeicherbelegung",
|
||||
"power-on-for-console": "Konsole ist nach Start der VM verfügbar",
|
||||
"power-state": "Energiezustand",
|
||||
"property": "Feld",
|
||||
"ram-usage": "Arbeitsspeicherbelegung",
|
||||
"reboot": "Neustart",
|
||||
"reformat": "Reformat",
|
||||
"relative-time": {
|
||||
"day": "1 Tag | {n} Tage",
|
||||
"future": "In {str}",
|
||||
"hour": "1 Stunde | {n} Stunden",
|
||||
"minute": "1 Minute | {n} Minuten",
|
||||
"month": "1 Monat | {n} Monate",
|
||||
"now": "Gerade eben",
|
||||
"past": "Vor {str}",
|
||||
"second": "1 Sekunde | {n} Sekunden",
|
||||
"year": "1 Jahr | {n} Jahre"
|
||||
},
|
||||
|
||||
"relative-time.day": "1 Tag | {n} Tage",
|
||||
"relative-time.future": "In {str}",
|
||||
"relative-time.hour": "1 Stunde | {n} Stunden",
|
||||
"relative-time.minute": "1 Minute | {n} Minuten",
|
||||
"relative-time.month": "1 Monat | {n} Monate",
|
||||
"relative-time.now": "Gerade eben",
|
||||
"relative-time.past": "Vor {str}",
|
||||
"relative-time.second": "1 Sekunde | {n} Sekunden",
|
||||
"relative-time.year": "1 Jahr | {n} Jahre",
|
||||
|
||||
"resume": "Fortsetzen",
|
||||
"save": "Speichern",
|
||||
"select-compression": "Kompression auswählen",
|
||||
@@ -183,10 +174,10 @@
|
||||
"selected-vms-in-execution": "Einige der ausgewählten VMs sind eingeschaltet",
|
||||
"send-ctrl-alt-del": "Ctrl+Alt+Del senden",
|
||||
"send-us-feedback": "Gib uns Feedback",
|
||||
"select": {
|
||||
"network": "Ein Netzwerk auswählen",
|
||||
"storage": "Einen Speicher auswählen"
|
||||
},
|
||||
|
||||
"select.network": "Ein Netzwerk auswählen",
|
||||
"select.storage": "Einen Speicher auswählen",
|
||||
|
||||
"settings": "Einstellungen",
|
||||
"shutdown": "Herunterfahren",
|
||||
"snapshot": "Snapshot",
|
||||
@@ -200,39 +191,33 @@
|
||||
"start": "Starten",
|
||||
"start-on-host": "Auf bestimmtem Host starten",
|
||||
"static-ip": "Statische IP",
|
||||
"stats": "Statistiken",
|
||||
"status": "Status",
|
||||
"storage": "Speicher",
|
||||
"storage-usage": "Belegung Storage",
|
||||
"support": "Support",
|
||||
"support-name": "{name} pro support",
|
||||
"suspend": "Standby",
|
||||
"switch-theme": "Theme wechseln",
|
||||
"system": "System",
|
||||
"task": {
|
||||
"estimated-end": "Vorraussichtliches Ende",
|
||||
"progress": "Fortschritt",
|
||||
"started": "Beginn"
|
||||
},
|
||||
"tasks": "Aufgaben",
|
||||
|
||||
"task.estimated-end": "Vorraussichtliches Ende",
|
||||
"task.progress": "Fortschritt",
|
||||
"task.started": "Beginn",
|
||||
|
||||
"theme-auto": "Auto",
|
||||
"theme-dark": "Dunkel",
|
||||
"theme-light": "Hell",
|
||||
"this-vm-cant-be-migrated": "Diese VM kann nicht migriert werden",
|
||||
"top-#": "Top {n}",
|
||||
"total": "Gesamt",
|
||||
"total-cpus": "Gesamt CPUs",
|
||||
"total-free": "Gesamt frei",
|
||||
"total-used": "Gesamt benutzt",
|
||||
"total-free:": "Gesamt frei :",
|
||||
"total-used:": "Gesamt benutzt :",
|
||||
"unreachable-hosts": "Hosts nicht erreichbar",
|
||||
"unreachable-hosts-reload-page": "Abgeschlossen, bitte lade die Seite neu",
|
||||
"vcpus": "vCPUs",
|
||||
"vcpus-used": "vCPUs in Benutzung",
|
||||
"version": "Version",
|
||||
"vm": {
|
||||
"active": "Aktiv",
|
||||
"inactive": "Inaktiv"
|
||||
},
|
||||
|
||||
"vm.active": "Aktiv",
|
||||
"vm.inactive": "Inaktiv",
|
||||
|
||||
"vm-is-running": "Die VM ist eingeschalten",
|
||||
"vm-running": "VM eingeschalten | VMs eingeschalten",
|
||||
"vms": "VMs",
|
||||
|
||||
@@ -8,19 +8,18 @@
|
||||
"admin-login": "Admin login",
|
||||
"admin-password": "Admin password",
|
||||
"admin-password-confirm": "Confirm admin password",
|
||||
"alarm-type": {
|
||||
"cpu_usage": "CPU usage exceeds {n}%",
|
||||
"disk_usage": "Disk usage exceeds {n}%",
|
||||
"fs_usage": "FS usage exceeds {n}%",
|
||||
"log_fs_usage": "Log FS usage exceeds {n}%",
|
||||
"mem_usage": "Memory usage exceeds {n}%",
|
||||
"memory_free_kib": "Free memory falls below {n}%",
|
||||
"network_usage": "Network usage exceeds {n}%",
|
||||
"physical_utilisation": "Physical utilisation exceeds {n}%",
|
||||
"sr_io_throughput_total_per_host": "SR IO throughput total per host exceeds {n}%",
|
||||
"unknown": "Unknown alarm type"
|
||||
},
|
||||
"alarms": "Alarms",
|
||||
|
||||
"alarm-type.cpu_usage": "CPU usage exceeds {n}%",
|
||||
"alarm-type.disk_usage": "Disk usage exceeds {n}%",
|
||||
"alarm-type.fs_usage": "FS usage exceeds {n}%",
|
||||
"alarm-type.log_fs_usage": "Log FS usage exceeds {n}%",
|
||||
"alarm-type.mem_usage": "Memory usage exceeds {n}%",
|
||||
"alarm-type.memory_free_kib": "Free memory falls below {n}%",
|
||||
"alarm-type.network_usage": "Network usage exceeds {n}%",
|
||||
"alarm-type.physical_utilisation": "Physical utilisation exceeds {n}%",
|
||||
"alarm-type.sr_io_throughput_total_per_host": "SR IO throughput total per host exceeds {n}%",
|
||||
"alarm-type.unknown": "Unknown alarm type",
|
||||
|
||||
"all-good": "All good!",
|
||||
"allow-self-signed-ssl": "You may need to allow self-signed SSL certificates in your browser",
|
||||
"appearance": "Appearance",
|
||||
@@ -34,32 +33,29 @@
|
||||
"click-to-display-alarms": "Click to display alarms:",
|
||||
"click-to-return-default-pool": "Click here to return to the default pool",
|
||||
"close": "Close",
|
||||
"coming-soon": "Coming soon!",
|
||||
"community": "Community",
|
||||
"community-name": "{name} community",
|
||||
"configuration": "Configuration",
|
||||
"confirm-cancel": "Are you sure you want to cancel?",
|
||||
"confirm-delete": "You're about to delete {0}",
|
||||
"console": "Console",
|
||||
"console-unavailable": "Console unavailable",
|
||||
"copy": "Copy",
|
||||
"cpu-provisioning": "CPU provisioning",
|
||||
"cpu-provisioning-warning": "The number of vCPUs allocated exceeds the number of physical CPUs available. System performance could be affected",
|
||||
"cpu-usage": "CPU usage",
|
||||
"dashboard": "Dashboard",
|
||||
"delete": "Delete",
|
||||
"delete-vms": "Delete 1 VM | Delete {n} VMs",
|
||||
"deploy": "Deploy",
|
||||
"deploy-xoa": "Deploy XOA",
|
||||
"deploy-xoa-available-on-desktop": "XOA deployment is available on your desktop interface",
|
||||
"deploy-xoa-status": {
|
||||
"configuring": "Configuring XOA…",
|
||||
"importing": "Importing XOA…",
|
||||
"not-responding": "XOA is not responding",
|
||||
"ready": "XOA is ready!",
|
||||
"starting": "Starting XOA…",
|
||||
"waiting": "Waiting for XOA to respond…"
|
||||
},
|
||||
|
||||
"deploy-xoa-status.configuring": "Configuring XOA…",
|
||||
"deploy-xoa-status.importing": "Importing XOA…",
|
||||
"deploy-xoa-status.not-responding": "XOA is not responding",
|
||||
"deploy-xoa-status.ready": "XOA is ready!",
|
||||
"deploy-xoa-status.starting": "Starting XOA…",
|
||||
"deploy-xoa-status.waiting": "Waiting for XOA to respond…",
|
||||
|
||||
"descending": "descending",
|
||||
"description": "Description",
|
||||
"dhcp": "DHCP",
|
||||
@@ -68,7 +64,6 @@
|
||||
"dns": "DNS",
|
||||
"do-you-have-needs": "You have needs and/or expectations? Let us know",
|
||||
"documentation": "Documentation",
|
||||
"documentation-name": "{name} documentation",
|
||||
"edit-config": "Edit config",
|
||||
"enabled": "Enabled",
|
||||
"error-no-data": "Error, can't collect data.",
|
||||
@@ -81,24 +76,22 @@
|
||||
"export-vms": "Export VMs",
|
||||
"export-vms-manually-information": "Some VM exports were not able to start automatically, probably due to your browser settings. To export them, you should click on each one. (Alternatively, copy the link as well.)",
|
||||
"fetching-fresh-data": "Fetching fresh data",
|
||||
"filter": {
|
||||
"comparison": {
|
||||
"contains": "Contains",
|
||||
"ends-with": "Ends with",
|
||||
"equals": "Equals",
|
||||
"is": "Is",
|
||||
"is-false": "Is false",
|
||||
"is-not": "Is not",
|
||||
"is-true": "Is true",
|
||||
"matches-regex": "Matches regex",
|
||||
"not-contain": "Doesn't contain",
|
||||
"not-end-with": "Doesn't end with",
|
||||
"not-equal": "Doesn't equal",
|
||||
"not-match-regex": "Doesn't match regex",
|
||||
"not-start-with": "Doesn't start with",
|
||||
"starts-with": "Starts with"
|
||||
}
|
||||
},
|
||||
|
||||
"filter.comparison.contains": "Contains",
|
||||
"filter.comparison.ends-with": "Ends with",
|
||||
"filter.comparison.equals": "Equals",
|
||||
"filter.comparison.is": "Is",
|
||||
"filter.comparison.is-false": "Is false",
|
||||
"filter.comparison.is-not": "Is not",
|
||||
"filter.comparison.is-true": "Is true",
|
||||
"filter.comparison.matches-regex": "Matches regex",
|
||||
"filter.comparison.not-contain": "Doesn't contain",
|
||||
"filter.comparison.not-end-with": "Doesn't end with",
|
||||
"filter.comparison.not-equal": "Doesn't equal",
|
||||
"filter.comparison.not-match-regex": "Doesn't match regex",
|
||||
"filter.comparison.not-start-with": "Doesn't start with",
|
||||
"filter.comparison.starts-with": "Starts with",
|
||||
|
||||
"following-hosts-unreachable": "The following hosts are unreachable",
|
||||
"force-reboot": "Force reboot",
|
||||
"force-shutdown": "Force shutdown",
|
||||
@@ -110,10 +103,10 @@
|
||||
"go-back": "Go back",
|
||||
"gzip": "gzip",
|
||||
"here": "Here",
|
||||
"host": {
|
||||
"active": "Active",
|
||||
"inactive": "Inactive"
|
||||
},
|
||||
|
||||
"host.active": "Active",
|
||||
"host.inactive": "Inactive",
|
||||
|
||||
"hosts": "Hosts",
|
||||
"invalid-field": "Invalid field",
|
||||
"keep-me-logged": "Keep me logged in",
|
||||
@@ -133,7 +126,6 @@
|
||||
"n-vms": "1 VM | {n} VMs",
|
||||
"name": "Name",
|
||||
"netmask": "Netmask",
|
||||
"network": "Network",
|
||||
"network-download": "Download",
|
||||
"network-throughput": "Network throughput",
|
||||
"network-upload": "Upload",
|
||||
@@ -160,23 +152,22 @@
|
||||
"please-confirm": "Please confirm",
|
||||
"pool-cpu-usage": "Pool CPU Usage",
|
||||
"pool-ram-usage": "Pool RAM Usage",
|
||||
"power-on-for-console": "Power on your VM to access its console",
|
||||
"power-state": "Power state",
|
||||
"property": "Property",
|
||||
"ram-usage": "RAM usage",
|
||||
"reboot": "Reboot",
|
||||
"reformat": "Reformat",
|
||||
"relative-time": {
|
||||
"day": "1 day | {n} days",
|
||||
"future": "In {str}",
|
||||
"hour": "1 hour | {n} hours",
|
||||
"minute": "1 minute | {n} minutes",
|
||||
"month": "1 month | {n} months",
|
||||
"now": "Just now",
|
||||
"past": "{str} ago",
|
||||
"second": "1 second | {n} seconds",
|
||||
"year": "1 year | {n} years"
|
||||
},
|
||||
|
||||
"relative-time.day": "1 day | {n} days",
|
||||
"relative-time.future": "In {str}",
|
||||
"relative-time.hour": "1 hour | {n} hours",
|
||||
"relative-time.minute": "1 minute | {n} minutes",
|
||||
"relative-time.month": "1 month | {n} months",
|
||||
"relative-time.now": "Just now",
|
||||
"relative-time.past": "{str} ago",
|
||||
"relative-time.second": "1 second | {n} seconds",
|
||||
"relative-time.year": "1 year | {n} years",
|
||||
|
||||
"resume": "Resume",
|
||||
"save": "Save",
|
||||
"select-compression": "Select a compression",
|
||||
@@ -184,10 +175,10 @@
|
||||
"selected-vms-in-execution": "Some selected VMs are running",
|
||||
"send-ctrl-alt-del": "Send Ctrl+Alt+Del",
|
||||
"send-us-feedback": "Send us feedback",
|
||||
"select": {
|
||||
"network": "Select a network",
|
||||
"storage": "Select a storage"
|
||||
},
|
||||
|
||||
"select.network": "Select a network",
|
||||
"select.storage": "Select a storage",
|
||||
|
||||
"settings": "Settings",
|
||||
"shutdown": "Shutdown",
|
||||
"snapshot": "Snapshot",
|
||||
@@ -201,21 +192,16 @@
|
||||
"start": "Start",
|
||||
"start-on-host": "Start on specific host",
|
||||
"static-ip": "Static IP",
|
||||
"stats": "Stats",
|
||||
"status": "Status",
|
||||
"storage": "Storage",
|
||||
"storage-usage": "Storage usage",
|
||||
"support": "Support",
|
||||
"support-name": "{name} pro support",
|
||||
"suspend": "Suspend",
|
||||
"switch-theme": "Switch theme",
|
||||
"system": "System",
|
||||
"task": {
|
||||
"estimated-end": "Estimated end",
|
||||
"progress": "Progress",
|
||||
"started": "Started"
|
||||
},
|
||||
"tasks": "Tasks",
|
||||
|
||||
"task.estimated-end": "Estimated end",
|
||||
"task.progress": "Progress",
|
||||
"task.started": "Started",
|
||||
|
||||
"theme-auto": "Auto",
|
||||
"theme-dark": "Dark",
|
||||
"theme-light": "Light",
|
||||
@@ -223,17 +209,17 @@
|
||||
"top-#": "Top {n}",
|
||||
"total": "Total",
|
||||
"total-cpus": "Total CPUs",
|
||||
"total-free": "Total free",
|
||||
"total-used": "Total used",
|
||||
"total-free:": "Total free:",
|
||||
"total-used:": "Total used:",
|
||||
"unreachable-hosts": "Unreachable hosts",
|
||||
"unreachable-hosts-reload-page": "Done, reload the page",
|
||||
"vcpus": "vCPUs",
|
||||
"vcpus-used": "vCPUs used",
|
||||
"version": "Version",
|
||||
"vm": {
|
||||
"active": "Active",
|
||||
"inactive": "Inactive"
|
||||
},
|
||||
|
||||
"vm.active": "Active",
|
||||
"vm.inactive": "Inactive",
|
||||
|
||||
"vm-is-running": "The VM is running",
|
||||
"vm-running": "VM running | VMs running",
|
||||
"vms": "VMs",
|
||||
|
||||
@@ -8,19 +8,18 @@
|
||||
"admin-login": "Nom d'utilisateur administrateur",
|
||||
"admin-password": "Mot de passe administrateur",
|
||||
"admin-password-confirm": "Confirmer le mot de passe administrateur",
|
||||
"alarm-type": {
|
||||
"cpu_usage": "L'utilisation du CPU dépasse {n}%",
|
||||
"disk_usage": "L'utilisation du disque dépasse {n}%",
|
||||
"fs_usage": "L'utilisation de FS dépasse {n}%",
|
||||
"log_fs_usage": "L'utilisation de Log FS dépasse {n}%",
|
||||
"mem_usage": "L'utilisation de la mémoire dépasse {n}%",
|
||||
"memory_free_kib": "La mémoire libre est inférieure à {n}%",
|
||||
"network_usage": "L'utilisation du réseau dépasse {n}%",
|
||||
"physical_utilisation": "L'utilisation physique dépasse {n}%",
|
||||
"sr_io_throughput_total_per_host": "Le débit total de l'IO SR par hôte dépasse {n}%",
|
||||
"unknown": "Type d'alarme inconnu"
|
||||
},
|
||||
"alarms": "Alarmes",
|
||||
|
||||
"alarm-type.cpu_usage": "L'utilisation du CPU dépasse {n}%",
|
||||
"alarm-type.disk_usage": "L'utilisation du disque dépasse {n}%",
|
||||
"alarm-type.fs_usage": "L'utilisation de FS dépasse {n}%",
|
||||
"alarm-type.log_fs_usage": "L'utilisation de Log FS dépasse {n}%",
|
||||
"alarm-type.mem_usage": "L'utilisation de la mémoire dépasse {n}%",
|
||||
"alarm-type.memory_free_kib": "La mémoire libre est inférieure à {n}%",
|
||||
"alarm-type.network_usage": "L'utilisation du réseau dépasse {n}%",
|
||||
"alarm-type.physical_utilisation": "L'utilisation physique dépasse {n}%",
|
||||
"alarm-type.sr_io_throughput_total_per_host": "Le débit total de l'IO SR par hôte dépasse {n}%",
|
||||
"alarm-type.unknown": "Type d'alarme inconnu",
|
||||
|
||||
"all-good": "Tout va bien !",
|
||||
"allow-self-signed-ssl": "Vous devrez peut-être autoriser les certificats SSL auto-signés depuis votre navigateur",
|
||||
"appearance": "Apparence",
|
||||
@@ -34,32 +33,29 @@
|
||||
"click-to-display-alarms": "Cliquer pour afficher les alarmes :",
|
||||
"click-to-return-default-pool": "Cliquer ici pour revenir au pool par défaut",
|
||||
"close": "Fermer",
|
||||
"coming-soon": "Bientôt disponible !",
|
||||
"community": "Communauté",
|
||||
"community-name": "Communauté {name}",
|
||||
"configuration": "Configuration",
|
||||
"confirm-cancel": "Êtes-vous sûr de vouloir annuler ?",
|
||||
"confirm-delete": "Vous êtes sur le point de supprimer {0}",
|
||||
"console": "Console",
|
||||
"console-unavailable": "Console indisponible",
|
||||
"copy": "Copier",
|
||||
"cpu-provisioning": "Provisionnement CPU",
|
||||
"cpu-provisioning-warning": "Le nombre de vCPU alloués dépasse le nombre de CPU physique disponible. Les performances du système pourraient être affectées",
|
||||
"cpu-usage": "Utilisation CPU",
|
||||
"dashboard": "Tableau de bord",
|
||||
"delete": "Supprimer",
|
||||
"delete-vms": "Supprimer 1 VM | Supprimer {n} VMs",
|
||||
"deploy": "Déployer",
|
||||
"deploy-xoa": "Déployer XOA",
|
||||
"deploy-xoa-available-on-desktop": "Le déploiement de la XOA est disponible sur ordinateur",
|
||||
"deploy-xoa-status": {
|
||||
"configuring": "Configuration de la XOA…",
|
||||
"importing": "Importation de la XOA…",
|
||||
"not-responding": "La XOA ne répond pas",
|
||||
"ready": "La XOA est prête !",
|
||||
"starting": "Démarrage de la XOA…",
|
||||
"waiting": "En attente de réponse de la XOA…"
|
||||
},
|
||||
|
||||
"deploy-xoa-status.configuring": "Configuration de la XOA…",
|
||||
"deploy-xoa-status.importing": "Importation de la XOA…",
|
||||
"deploy-xoa-status.not-responding": "La XOA ne répond pas",
|
||||
"deploy-xoa-status.ready": "La XOA est prête !",
|
||||
"deploy-xoa-status.starting": "Démarrage de la XOA…",
|
||||
"deploy-xoa-status.waiting": "En attente de réponse de la XOA…",
|
||||
|
||||
"descending": "descendant",
|
||||
"description": "Description",
|
||||
"dhcp": "DHCP",
|
||||
@@ -68,7 +64,6 @@
|
||||
"display": "Affichage",
|
||||
"do-you-have-needs": "Vous avez des besoins et/ou des attentes ? Faites le nous savoir",
|
||||
"documentation": "Documentation",
|
||||
"documentation-name": "Documentation {name}",
|
||||
"edit-config": "Modifier config",
|
||||
"enabled": "Activé",
|
||||
"error-no-data": "Erreur, impossible de collecter les données.",
|
||||
@@ -81,24 +76,22 @@
|
||||
"export-vms": "Exporter les VMs",
|
||||
"export-vms-manually-information": "Certaines exportations de VMs n'ont pas pu démarrer automatiquement, peut-être en raison des paramètres du navigateur. Pour les exporter, vous devrez cliquer sur chacune d'entre elles. (Ou copier le lien.)",
|
||||
"fetching-fresh-data": "Récupération de données à jour",
|
||||
"filter": {
|
||||
"comparison": {
|
||||
"contains": "Contient",
|
||||
"ends-with": "Termine par",
|
||||
"equals": "Est égal à",
|
||||
"is": "Est",
|
||||
"is-false": "Est faux",
|
||||
"is-not": "N'est pas",
|
||||
"is-true": "Est vrai",
|
||||
"matches-regex": "Correspond à la regex",
|
||||
"not-contain": "Ne contient pas",
|
||||
"not-end-with": "Ne termine pas par",
|
||||
"not-equal": "N'est pas égal à",
|
||||
"not-match-regex": "Ne correspond pas à la regex",
|
||||
"not-start-with": "Ne commence pas par",
|
||||
"starts-with": "Commence par"
|
||||
}
|
||||
},
|
||||
|
||||
"filter.comparison.contains": "Contient",
|
||||
"filter.comparison.ends-with": "Termine par",
|
||||
"filter.comparison.equals": "Est égal à",
|
||||
"filter.comparison.is": "Est",
|
||||
"filter.comparison.is-false": "Est faux",
|
||||
"filter.comparison.is-not": "N'est pas",
|
||||
"filter.comparison.is-true": "Est vrai",
|
||||
"filter.comparison.matches-regex": "Correspond à la regex",
|
||||
"filter.comparison.not-contain": "Ne contient pas",
|
||||
"filter.comparison.not-end-with": "Ne termine pas par",
|
||||
"filter.comparison.not-equal": "N'est pas égal à",
|
||||
"filter.comparison.not-match-regex": "Ne correspond pas à la regex",
|
||||
"filter.comparison.not-start-with": "Ne commence pas par",
|
||||
"filter.comparison.starts-with": "Commence par",
|
||||
|
||||
"following-hosts-unreachable": "Les hôtes suivants sont inaccessibles",
|
||||
"force-reboot": "Forcer le redémarrage",
|
||||
"force-shutdown": "Forcer l'arrêt",
|
||||
@@ -110,10 +103,10 @@
|
||||
"go-back": "Revenir en arrière",
|
||||
"gzip": "gzip",
|
||||
"here": "Ici",
|
||||
"host": {
|
||||
"active": "Actif | Actif | Actifs",
|
||||
"inactive": "Inactif | Inactif | Inactifs"
|
||||
},
|
||||
|
||||
"host.active": "Actif | Actif | Actifs",
|
||||
"host.inactive": "Inactif | Inactif | Inactifs",
|
||||
|
||||
"hosts": "Hôtes",
|
||||
"invalid-field": "Champ invalide",
|
||||
"keep-me-logged": "Rester connecté",
|
||||
@@ -133,7 +126,6 @@
|
||||
"n-vms": "1 VM | {n} VMs",
|
||||
"name": "Nom",
|
||||
"netmask": "Masque réseau",
|
||||
"network": "Réseau",
|
||||
"network-download": "Descendant",
|
||||
"network-throughput": "Débit du réseau",
|
||||
"network-upload": "Montant",
|
||||
@@ -160,23 +152,22 @@
|
||||
"please-confirm": "Veuillez confirmer",
|
||||
"pool-cpu-usage": "Utilisation CPU du Pool",
|
||||
"pool-ram-usage": "Utilisation RAM du Pool",
|
||||
"power-on-for-console": "Allumez votre VM pour accéder à sa console",
|
||||
"power-state": "État d'alimentation",
|
||||
"property": "Propriété",
|
||||
"ram-usage": "Utilisation de la RAM",
|
||||
"reboot": "Redémarrer",
|
||||
"reformat": "Reformater",
|
||||
"relative-time": {
|
||||
"day": "1 jour | {n} jours",
|
||||
"future": "Dans {str}",
|
||||
"hour": "1 heure | {n} heures",
|
||||
"minute": "1 minute | {n} minutes",
|
||||
"month": "{n} mois",
|
||||
"now": "À l'instant",
|
||||
"past": "Il y a {str}",
|
||||
"second": "1 seconde | {n} secondes",
|
||||
"year": "1 an | {n} ans"
|
||||
},
|
||||
|
||||
"relative-time.day": "1 jour | {n} jours",
|
||||
"relative-time.future": "Dans {str}",
|
||||
"relative-time.hour": "1 heure | {n} heures",
|
||||
"relative-time.minute": "1 minute | {n} minutes",
|
||||
"relative-time.month": "{n} mois",
|
||||
"relative-time.now": "À l'instant",
|
||||
"relative-time.past": "Il y a {str}",
|
||||
"relative-time.second": "1 seconde | {n} secondes",
|
||||
"relative-time.year": "1 an | {n} ans",
|
||||
|
||||
"resume": "Reprendre",
|
||||
"save": "Enregistrer",
|
||||
"select-compression": "Sélectionnez une compression",
|
||||
@@ -184,10 +175,10 @@
|
||||
"selected-vms-in-execution": "Certaines VMs sélectionnées sont en cours d'exécution",
|
||||
"send-ctrl-alt-del": "Envoyer Ctrl+Alt+Suppr",
|
||||
"send-us-feedback": "Envoyez-nous vos commentaires",
|
||||
"select": {
|
||||
"network": "Sélectionner un réseau",
|
||||
"storage": "Sélectionner un SR"
|
||||
},
|
||||
|
||||
"select.network": "Sélectionner un réseau",
|
||||
"select.storage": "Sélectionner un SR",
|
||||
|
||||
"settings": "Paramètres",
|
||||
"shutdown": "Arrêter",
|
||||
"snapshot": "Instantané",
|
||||
@@ -201,21 +192,16 @@
|
||||
"start": "Démarrer",
|
||||
"start-on-host": "Démarrer sur un hôte spécifique",
|
||||
"static-ip": "IP statique",
|
||||
"stats": "Stats",
|
||||
"status": "Statut",
|
||||
"storage": "Stockage",
|
||||
"storage-usage": "Utilisation du stockage",
|
||||
"support": "Support",
|
||||
"support-name": "Support pro {name}",
|
||||
"suspend": "Suspendre",
|
||||
"switch-theme": "Changer de thème",
|
||||
"system": "Système",
|
||||
"task": {
|
||||
"estimated-end": "Fin estimée",
|
||||
"progress": "Progression",
|
||||
"started": "Démarré"
|
||||
},
|
||||
"tasks": "Tâches",
|
||||
|
||||
"task.estimated-end": "Fin estimée",
|
||||
"task.progress": "Progression",
|
||||
"task.started": "Démarré",
|
||||
|
||||
"theme-auto": "Auto",
|
||||
"theme-dark": "Sombre",
|
||||
"theme-light": "Clair",
|
||||
@@ -223,17 +209,17 @@
|
||||
"top-#": "Top {n}",
|
||||
"total": "Total",
|
||||
"total-cpus": "Total CPUs",
|
||||
"total-free": "Total libre",
|
||||
"total-used": "Total utilisé",
|
||||
"total-free:": "Total libre :",
|
||||
"total-used:": "Total utilisé :",
|
||||
"unreachable-hosts": "Hôtes inaccessibles",
|
||||
"unreachable-hosts-reload-page": "C'est fait. Rafraîchir la page",
|
||||
"vcpus": "vCPUs",
|
||||
"vcpus-used": "vCPUs utilisés",
|
||||
"version": "Version",
|
||||
"vm": {
|
||||
"active": "Active | Active | Actives",
|
||||
"inactive": "Inactive | Inactive | Inactives"
|
||||
},
|
||||
|
||||
"vm.active": "Active | Active | Actives",
|
||||
"vm.inactive": "Inactive | Inactive | Inactives",
|
||||
|
||||
"vm-is-running": "La VM est en cours d'exécution",
|
||||
"vm-running": "VM en cours d'exécution | VMs en cours d'exécution",
|
||||
"vms": "VMs",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>Chargement en cours...</template>
|
||||
<template>{{ $t('loading-in-progress') }}</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { usePoolStore } from '@/stores/xen-api/pool.store'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<img alt="Not found" src="../assets/object-not-found.svg" />
|
||||
<img alt="" src="../assets/object-not-found.svg" />
|
||||
<p class="text">{{ $t('object-not-found', { id }) }}</p>
|
||||
<UiButton @click="router.push({ name: 'home' })">{{ $t('back-pool-dashboard') }}</UiButton>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<img alt="Not found" src="../assets/page-not-found.svg" />
|
||||
<img alt="" src="../assets/page-not-found.svg" />
|
||||
<p class="numeric">404</p>
|
||||
<p class="text">{{ $t('page-not-found') }}</p>
|
||||
<UiButton @click="router.push({ name: 'home' })">{{ $t('back-pool-dashboard') }}</UiButton>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<UiCard class="pool-vms-view">
|
||||
<UiCardTitle subtitle>
|
||||
VMs
|
||||
{{ $t('vms') }}
|
||||
<template v-if="isMobile" #right>
|
||||
<VmsActionsBar :selected-refs="selectedVmsRefs" />
|
||||
</template>
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
<UiKeyValueRow>
|
||||
<template #key>{{ $t('version') }}</template>
|
||||
<template #value>
|
||||
v{{ xoLiteVersion }}
|
||||
<code v-if="xoLiteGitHead"> ({{ xoLiteGitHead.slice(0, 5) }}) </code>
|
||||
{{ `v${xoLiteVersion}` }}
|
||||
<code v-if="xoLiteGitHead">{{ `(${xoLiteGitHead.slice(0, 5)})` }}</code>
|
||||
</template>
|
||||
</UiKeyValueRow>
|
||||
<UiKeyValueRow>
|
||||
@@ -37,7 +37,7 @@
|
||||
<UiKeyValueList>
|
||||
<UiKeyValueRow>
|
||||
<template #key>{{ $t('version') }}</template>
|
||||
<template #value>v{{ xcpVersion }}</template>
|
||||
<template #value>{{ `v${xcpVersion}` }}</template>
|
||||
</UiKeyValueRow>
|
||||
<UiKeyValueRow>
|
||||
<template #key>{{ $t('news') }}</template>
|
||||
@@ -85,9 +85,13 @@
|
||||
:class="{ selected: colorMode === colorModeOption }"
|
||||
@click="colorMode = colorModeOption"
|
||||
>
|
||||
<img v-if="colorModeOption === 'light'" src="@/assets/color-mode-light.svg" alt="Color mode light" />
|
||||
<img v-else-if="colorModeOption === 'dark'" src="@/assets/color-mode-dark.svg" alt="Color mode dark" />
|
||||
<img v-else src="@/assets/color-mode-auto.svg" alt="Color mode auto" />
|
||||
<img v-if="colorModeOption === 'light'" src="@/assets/color-mode-light.svg" :alt="$t('dark-mode.disable')" />
|
||||
<img
|
||||
v-else-if="colorModeOption === 'dark'"
|
||||
src="@/assets/color-mode-dark.svg"
|
||||
:alt="$t('dark-mode.enable')"
|
||||
/>
|
||||
<img v-else src="@/assets/color-mode-auto.svg" :alt="$t('dark-mode.auto')" />
|
||||
<span>
|
||||
<UiIcon v-if="colorMode === colorModeOption" :icon="faCheck" />
|
||||
{{ $t(`theme-${colorModeOption}`) }}
|
||||
@@ -114,10 +118,10 @@ import UiCard from '@/components/ui/UiCard.vue'
|
||||
import UiCardTitle from '@/components/ui/UiCardTitle.vue'
|
||||
import UiKeyValueList from '@/components/ui/UiKeyValueList.vue'
|
||||
import UiKeyValueRow from '@/components/ui/UiKeyValueRow.vue'
|
||||
import { locales } from '@/i18n'
|
||||
import { usePageTitleStore } from '@/stores/page-title.store'
|
||||
import { useHostStore } from '@/stores/xen-api/host.store'
|
||||
import { usePoolStore } from '@/stores/xen-api/pool.store'
|
||||
import { locales } from '@core/i18n'
|
||||
import { useUiStore } from '@core/stores/ui.store'
|
||||
import { faEarthAmericas, faGear, faCheck } from '@fortawesome/free-solid-svg-icons'
|
||||
import type { BasicColorSchema } from '@vueuse/core'
|
||||
|
||||
@@ -66,13 +66,13 @@
|
||||
:value="sr"
|
||||
:class="sr.physical_size - sr.physical_utilisation < REQUIRED_GB * 1024 ** 3 ? 'warning' : 'success'"
|
||||
>
|
||||
{{ sr.name_label }} -
|
||||
{{ `${sr.name_label} -` }}
|
||||
{{
|
||||
$t('n-gb-left', {
|
||||
n: Math.round((sr.physical_size - sr.physical_utilisation) / 1024 ** 3),
|
||||
})
|
||||
}}
|
||||
<span v-if="sr.physical_size - sr.physical_utilisation < REQUIRED_GB * 1024 ** 3">⚠️</span>
|
||||
<template v-if="sr.physical_size - sr.physical_utilisation < REQUIRED_GB * 1024 ** 3">⚠️</template>
|
||||
</option>
|
||||
</FormSelect>
|
||||
</FormInputWrapper>
|
||||
|
||||
162
@xen-orchestra/web-core/docs/guidelines/i18n.md
Normal file
162
@xen-orchestra/web-core/docs/guidelines/i18n.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Internationalization (i18n)
|
||||
|
||||
Internationalization of the app is done with [Vue-i18n](https://vue-i18n.intlify.dev/).
|
||||
|
||||
Sources of truth are `en.json` files in different projects.
|
||||
|
||||
## Translation files to use
|
||||
|
||||
| Target | Path | Notes |
|
||||
| ------------------------------- | ----------------------------- | --------------------- |
|
||||
| Shared between XO Lite and XO 6 | `web-core/lib/locales/*.json` | |
|
||||
| Specific to XO Lite | `lite/src/locales/*.json` | |
|
||||
| Specific to XO 6 | `web/src/locales/*.json` | |
|
||||
| Specific to XO Core | `web-core/lib/locales/*.json` | Prefixed with `core.` |
|
||||
|
||||
## Translation keys
|
||||
|
||||
Translation keys MUST be in English and SHOULD use kebab-case.
|
||||
|
||||
Translation keys MUST NOT be nested. To group keys, use `prefix.key: value` instead of `prefix: { key: value }`.
|
||||
|
||||
Translation keys MUST be sorted alphabetically.
|
||||
|
||||
As a bonus, this will allow the usage of `foo` and `foo.bar` as separate keys.
|
||||
|
||||
Separate groups with a blank line.
|
||||
|
||||
❌ BAD
|
||||
|
||||
```json
|
||||
{
|
||||
"bonjour": "Hello",
|
||||
"foo_bar": "Foo Bar",
|
||||
"a": "A",
|
||||
"b": {
|
||||
"foo": "B Foo",
|
||||
"bar": "B Bar",
|
||||
"baz": "B Baz"
|
||||
},
|
||||
"c": "C"
|
||||
}
|
||||
```
|
||||
|
||||
✅ GOOD
|
||||
|
||||
```json
|
||||
{
|
||||
"a": "A",
|
||||
|
||||
"b.bar": "B Bar",
|
||||
"b.baz": "B Baz",
|
||||
"b.foo": "B Foo",
|
||||
|
||||
"c": "C",
|
||||
"foo-bar": "Foo Bar",
|
||||
"hello": "Hello"
|
||||
}
|
||||
```
|
||||
|
||||
## Punctuation
|
||||
|
||||
Strings punctuations should be included in the translation key.
|
||||
|
||||
This allows better adapting the punctuation to the rules of the target language.
|
||||
|
||||
For example:
|
||||
|
||||
- in English, interrogative sentences end with a question mark with no space before it
|
||||
- in French, interrogative sentences end with a question mark with a space before it
|
||||
- in Spanish, interrogative sentences start with an inverted question mark and end with a question mark with no spaces
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Since HTML is not accepted in translations, you must use a non-breaking space character (` `) instead of ` `
|
||||
|
||||
### Example:
|
||||
|
||||
#### English
|
||||
|
||||
```json
|
||||
{
|
||||
"confirm": "Confirm",
|
||||
"confirm?": "Confirm?",
|
||||
"warning": "Warning",
|
||||
"warning!:": "Warning!"
|
||||
}
|
||||
```
|
||||
|
||||
#### French
|
||||
|
||||
```json
|
||||
{
|
||||
"confirm": "Confirmer",
|
||||
"confirm?": "Confirmer ?",
|
||||
"warning": "Avertissement",
|
||||
"warning!:": "Attention !"
|
||||
}
|
||||
```
|
||||
|
||||
#### Spanish
|
||||
|
||||
```json
|
||||
{
|
||||
"confirm": "Confirmar",
|
||||
"confirm?": "¿Confirmar?",
|
||||
"warning": "Advertencia",
|
||||
"warning!:": "¡Atención!"
|
||||
}
|
||||
```
|
||||
|
||||
## Percentages
|
||||
|
||||
To include a percentage in a translation, use `$n(value, 'percent')`.
|
||||
|
||||
The value will be rounded to two decimal places maximum.
|
||||
|
||||
## Numbers
|
||||
|
||||
To include a number in a translation, use `$n(value)`.
|
||||
|
||||
## Dates and times
|
||||
|
||||
To include a date or a time in a translation, use `$d(value, '<format>')`.
|
||||
|
||||
### Example
|
||||
|
||||
```html
|
||||
<p>{{ $d(date, "date_short") }}</p>
|
||||
<!-- 9/10/2022 -->
|
||||
<p>{{ $d(date, "date_medium") }}</p>
|
||||
<!-- Sep 10, 2022 -->
|
||||
<p>{{ $d(date, "date_long") }}</p>
|
||||
<!-- September 10, 2022 -->
|
||||
<p>{{ $d(date, "datetime_short") }}</p>
|
||||
<!-- 9/10/2022, 06:30 PM -->
|
||||
<p>{{ $d(date, "datetime_medium") }}</p>
|
||||
<!-- Sep 10, 2022, 06:30 PM -->
|
||||
<p>{{ $d(date, "datetime_long") }}</p>
|
||||
<!-- September 10, 2022 at 06:30 PM -->
|
||||
<p>{{ $d(date, "time") }}</p>
|
||||
<!-- 06:30 PM -->
|
||||
```
|
||||
|
||||
## Literal strings
|
||||
|
||||
Literal strings are not allowed in Vue templates.
|
||||
|
||||
If you really need to **exceptionally** include a literal string, you can either:
|
||||
|
||||
- use the mustache syntax with concatenation
|
||||
|
||||
```html
|
||||
<!-- ❌ BAD -->
|
||||
<div>v{{ version }}</div>
|
||||
|
||||
<!-- ✅ GOOD -->
|
||||
<div>{{ `v${version}` }}</div>
|
||||
```
|
||||
|
||||
- add the string as an exception in `.eslintrc.js` for the `@intlify/vue-i18n/no-raw-text` rule
|
||||
|
||||
> [!TIP]
|
||||
> In most cases, literal strings will not be necessary. Think twice before using them.
|
||||
1
@xen-orchestra/web-core/env.d.ts
vendored
1
@xen-orchestra/web-core/env.d.ts
vendored
@@ -1 +1,2 @@
|
||||
/// <reference types="novnc__novnc" />
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
<div class="card-numbers" :class="size">
|
||||
<span class="label typo" :class="labelFontClass">{{ label }}</span>
|
||||
<div class="values" :class="size">
|
||||
<span v-if="size === 'small' && max" class="value typo c2-semi-bold">{{ valueAsPercentage }}%</span>
|
||||
<span v-if="size === 'small' && max" class="value typo c2-semi-bold">
|
||||
{{ $n(valueAsPercentage, 'percent') }}
|
||||
</span>
|
||||
|
||||
<div class="value typo" :class="valueFontClass">
|
||||
{{ value }}<span class="unit typo" :class="unitFontClass">{{ unit }}</span>
|
||||
@@ -33,10 +35,10 @@ const unitFontClass = computed(() => (props.size === 'medium' ? 'p2-medium' : 'c
|
||||
|
||||
const valueAsPercentage = computed(() => {
|
||||
if (props.max === undefined) {
|
||||
return
|
||||
return 0
|
||||
}
|
||||
|
||||
return ((props.value / props.max) * 100).toFixed(1)
|
||||
return props.value / props.max
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -9,8 +9,12 @@
|
||||
<slot />
|
||||
</div>
|
||||
<div v-if="onToggleSelectAll" class="buttons">
|
||||
<span v-if="selected !== 'all'" @click="emit('toggleSelectAll', true)">Select all</span>
|
||||
<span v-if="selected !== 'none'" @click="emit('toggleSelectAll', false)">Deselect all</span>
|
||||
<span v-if="selected !== 'all'" @click="emit('toggleSelectAll', true)">
|
||||
{{ $t('core.select.all') }}
|
||||
</span>
|
||||
<span v-if="selected !== 'none'" @click="emit('toggleSelectAll', false)">
|
||||
{{ $t('core.select.none') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
:style="{ width: percentage + '%' }"
|
||||
class="stacked-bar-segment typo c4-semi-bold"
|
||||
>
|
||||
<div ref="ellipsisElement" :class="{ hidden }" class="ellipsis">{{ percentage.toFixed(0) }} %</div>
|
||||
<div ref="ellipsisElement" :class="{ hidden }" class="ellipsis">
|
||||
{{ $n(percentage / 100, 'percent') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<MenuItem
|
||||
v-for="interaction in interactions"
|
||||
:key="interaction.id"
|
||||
v-tooltip="$t('core.coming-soon')"
|
||||
v-tooltip="$t('coming-soon')"
|
||||
:disabled="interaction.disabled"
|
||||
:on-click="() => updateInteraction(interaction)"
|
||||
>
|
||||
|
||||
@@ -27,6 +27,15 @@ export default createI18n({
|
||||
locale: localStorage.getItem('lang') ?? 'en',
|
||||
fallbackLocale: 'en',
|
||||
messages,
|
||||
missing: (locale, key, vm) => {
|
||||
if (!import.meta.env.DEV) {
|
||||
return key
|
||||
}
|
||||
|
||||
console.warn(`i18n key not found: ${key}`, `Used in ${vm?.type.__name ?? 'unknown component'}`)
|
||||
|
||||
return `🌎❗⟨${key}⟩`
|
||||
},
|
||||
datetimeFormats: {
|
||||
en: {
|
||||
date_short: {
|
||||
@@ -155,4 +164,27 @@ export default createI18n({
|
||||
},
|
||||
},
|
||||
},
|
||||
numberFormats: {
|
||||
en: {
|
||||
percent: {
|
||||
style: 'percent',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
},
|
||||
},
|
||||
fr: {
|
||||
percent: {
|
||||
style: 'percent',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
},
|
||||
},
|
||||
de: {
|
||||
percent: {
|
||||
style: 'percent',
|
||||
minimumFractionDigits: 0,
|
||||
maximumFractionDigits: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
{
|
||||
"core": {
|
||||
"close": "Schließen",
|
||||
"log-out": "Abmelden"
|
||||
}
|
||||
"alarms": "Alarme",
|
||||
|
||||
"bytes.ki": "KiB",
|
||||
"bytes.mi": "MiB",
|
||||
"bytes.gi": "GiB",
|
||||
|
||||
"coming-soon": "Bald verfügbar!",
|
||||
"console": "Konsole",
|
||||
|
||||
"core.close": "Schließen",
|
||||
|
||||
"core.select.all": "Alles auswählen",
|
||||
"core.select.none": "Alle abwählen",
|
||||
|
||||
"dark-mode.enable": "Aktivieren Sie den Dunkelmodus",
|
||||
"dark-mode.disable": "Deaktivieren Sie den Dunkelmodus",
|
||||
"dark-mode.auto": "Automatischer Dunkelmodus",
|
||||
|
||||
"dashboard": "Dashboard",
|
||||
"documentation-name": "{name} Dokumentation",
|
||||
"loading-in-progress": "Ladevorgang läuft…",
|
||||
"log-out": "Abmelden",
|
||||
"master": "Primärer Host",
|
||||
"network": "Netzwerk",
|
||||
"power-on-for-console": "Konsole ist nach Start der VM verfügbar",
|
||||
"stats": "Statistiken",
|
||||
"storage": "Speicher",
|
||||
"support-name": "{name} pro support",
|
||||
"system": "System",
|
||||
"tasks": "Aufgaben"
|
||||
}
|
||||
|
||||
@@ -1,24 +1,46 @@
|
||||
{
|
||||
"core": {
|
||||
"close": "Close",
|
||||
"coming-soon": "Coming soon!",
|
||||
"current": "Current",
|
||||
"filter": "Filter",
|
||||
"group": "Group",
|
||||
"hide": "Hide",
|
||||
"log-out": "Log out",
|
||||
"master": "Primary host",
|
||||
"open": "Open",
|
||||
"quick-actions": "Quick actions",
|
||||
"sidebar": {
|
||||
"close": "Close sidebar",
|
||||
"lock": "Lock sidebar open",
|
||||
"open": "Open sidebar",
|
||||
"unlock": "Unlock sidebar"
|
||||
},
|
||||
"sort": {
|
||||
"ascending": "Sort ascending",
|
||||
"descending": "Sort descending"
|
||||
}
|
||||
}
|
||||
"alarms": "Alarms",
|
||||
|
||||
"bytes.ki": "KiB",
|
||||
"bytes.mi": "MiB",
|
||||
"bytes.gi": "GiB",
|
||||
|
||||
"coming-soon": "Coming soon!",
|
||||
"console": "Console",
|
||||
|
||||
"core.close": "Close",
|
||||
"core.current": "Current",
|
||||
"core.filter": "Filter",
|
||||
"core.group": "Group",
|
||||
"core.hide": "Hide",
|
||||
"core.open": "Open",
|
||||
"core.quick-actions": "Quick actions",
|
||||
|
||||
"core.select.all": "Select all",
|
||||
"core.select.none": "Select none",
|
||||
|
||||
"core.sidebar.close": "Close sidebar",
|
||||
"core.sidebar.lock": "Lock sidebar open",
|
||||
"core.sidebar.open": "Open sidebar",
|
||||
"core.sidebar.unlock": "Unlock sidebar",
|
||||
|
||||
"core.sort.ascending": "Sort ascending",
|
||||
"core.sort.descending": "Sort descending",
|
||||
|
||||
"dark-mode.enable": "Enable dark mode",
|
||||
"dark-mode.disable": "Disable dark mode",
|
||||
"dark-mode.auto": "Auto dark mode",
|
||||
|
||||
"dashboard": "Dashboard",
|
||||
"documentation-name": "{name} documentation",
|
||||
"loading-in-progress": "Loading in progress…",
|
||||
"log-out": "Log out",
|
||||
"master": "Primary host",
|
||||
"network": "Network",
|
||||
"power-on-for-console": "Power on your VM to access its console",
|
||||
"stats": "Stats",
|
||||
"storage": "Storage",
|
||||
"support-name": "{name} pro support",
|
||||
"system": "System",
|
||||
"tasks": "Tasks"
|
||||
}
|
||||
|
||||
@@ -1,24 +1,46 @@
|
||||
{
|
||||
"core": {
|
||||
"close": "Fermer",
|
||||
"coming-soon": "Bientôt disponible !",
|
||||
"current": "Actuel",
|
||||
"filter": "Filtrer",
|
||||
"group": "Grouper",
|
||||
"hide": "Masquer",
|
||||
"log-out": "Se déconnecter",
|
||||
"master": "Hôte primaire",
|
||||
"open": "Ouvrir",
|
||||
"quick-actions": "Actions rapides",
|
||||
"sidebar": {
|
||||
"close": "Fermer la barre latérale",
|
||||
"lock": "Verrouiller la barre latérale",
|
||||
"open": "Ouvrir la barre latérale",
|
||||
"unlock": "Déverrouiller la barre latérale"
|
||||
},
|
||||
"sort": {
|
||||
"ascending": "Trier par ordre croissant",
|
||||
"descending": "Trier par ordre décroissant"
|
||||
}
|
||||
}
|
||||
"alarms": "Alarmes",
|
||||
|
||||
"bytes.ki": "Kio",
|
||||
"bytes.mi": "Mio",
|
||||
"bytes.gi": "Gio",
|
||||
|
||||
"coming-soon": "Bientôt disponible !",
|
||||
"console": "Console",
|
||||
|
||||
"core.close": "Fermer",
|
||||
"core.current": "Actuel",
|
||||
"core.filter": "Filtrer",
|
||||
"core.group": "Grouper",
|
||||
"core.hide": "Masquer",
|
||||
"core.open": "Ouvrir",
|
||||
"core.quick-actions": "Actions rapides",
|
||||
|
||||
"core.select.all": "Tout sélectionner",
|
||||
"core.select.none": "Tout désélectionner",
|
||||
|
||||
"core.sidebar.close": "Fermer la barre latérale",
|
||||
"core.sidebar.lock": "Verrouiller la barre latérale",
|
||||
"core.sidebar.open": "Ouvrir la barre latérale",
|
||||
"core.sidebar.unlock": "Déverrouiller la barre latérale",
|
||||
|
||||
"core.sort.ascending": "Trier par ordre croissant",
|
||||
"core.sort.descending": "Trier par ordre décroissant",
|
||||
|
||||
"dark-mode.enable": "Activer le mode sombre",
|
||||
"dark-mode.disable": "Désactiver le mode sombre",
|
||||
"dark-mode.auto": "Mode sombre automatique",
|
||||
|
||||
"dashboard": "Tableau de bord",
|
||||
"documentation-name": "Documentation {name}",
|
||||
"loading-in-progress": "Chargement en cours…",
|
||||
"log-out": "Se déconnecter",
|
||||
"master": "Hôte primaire",
|
||||
"network": "Réseau",
|
||||
"power-on-for-console": "Allumez votre VM pour accéder à sa console",
|
||||
"stats": "Stats",
|
||||
"storage": "Stockage",
|
||||
"support-name": "Support pro {name}",
|
||||
"system": "Système",
|
||||
"tasks": "Tâches"
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</a>
|
||||
</MenuItem>
|
||||
<MenuItem :icon="faArrowRightFromBracket" class="logout" @click="logout()">
|
||||
{{ $t('core.log-out') }}
|
||||
{{ $t('log-out') }}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TreeItemLabel :icon="faServer" :no-indent="!hasVMs" :route="`/host/${host.id}`">
|
||||
{{ host.name_label }}
|
||||
<template #addons>
|
||||
<UiIcon v-if="isMaster" v-tooltip="$t('core.master')" :icon="faStar" color="warning" />
|
||||
<UiIcon v-if="isMaster" v-tooltip="$t('master')" :icon="faStar" color="warning" />
|
||||
</template>
|
||||
</TreeItemLabel>
|
||||
<template v-if="hasVMs" #sublist>
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<h4 v-tooltip class="typo h4-medium title">{{ name }}</h4>
|
||||
</div>
|
||||
<TabList>
|
||||
<TabItem disabled>Dashboard</TabItem>
|
||||
<TabItem active>Console</TabItem>
|
||||
<TabItem disabled>Alarms</TabItem>
|
||||
<TabItem disabled>Stats</TabItem>
|
||||
<TabItem disabled>System</TabItem>
|
||||
<TabItem disabled>Network</TabItem>
|
||||
<TabItem disabled>Storage</TabItem>
|
||||
<TabItem disabled>Tasks</TabItem>
|
||||
<TabItem disabled>{{ $t('dashboard') }}</TabItem>
|
||||
<TabItem active>{{ $t('console') }}</TabItem>
|
||||
<TabItem disabled>{{ $t('alarms') }}</TabItem>
|
||||
<TabItem disabled>{{ $t('stats') }}</TabItem>
|
||||
<TabItem disabled>{{ $t('system') }}</TabItem>
|
||||
<TabItem disabled>{{ $t('network') }}</TabItem>
|
||||
<TabItem disabled>{{ $t('storage') }}</TabItem>
|
||||
<TabItem disabled>{{ $t('tasks') }}</TabItem>
|
||||
</TabList>
|
||||
</template>
|
||||
|
||||
|
||||
4
@xen-orchestra/web/src/locales/de.json
Normal file
4
@xen-orchestra/web/src/locales/de.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"account-organization-more": "Konto, Organisation & mehr…",
|
||||
"tasks.quick-view": "Schnellansicht der Aufgaben (Bald verfügbar)"
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
{
|
||||
"account-organization-more": "Account, organization & more...",
|
||||
"documentation-name": "{name} documentation",
|
||||
"power-on-for-console": "Power on your VM to access its console",
|
||||
"support-name": "{name} pro support",
|
||||
"tasks": {
|
||||
"quick-view": "Tasks' quick view (coming soon)"
|
||||
}
|
||||
"account-organization-more": "Account, organization & more…",
|
||||
"tasks.quick-view": "Tasks' quick view (coming soon)"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
{
|
||||
"account-organization-more": "Compte, organisation et plus…",
|
||||
"documentation-name": "Documentation {name}",
|
||||
"power-on-for-console": "Allumez votre VM pour accéder à sa console",
|
||||
"support-name": "Support pro {name}",
|
||||
"tasks": {
|
||||
"quick-view": "Vue rapide des tâches (bientôt disponible)"
|
||||
}
|
||||
"tasks.quick-view": "Vue rapide des tâches (bientôt disponible)"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<template #content> Coming soon</template>
|
||||
<template #content>{{ $t('coming-soon') }}</template>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<template #content>Welcome to XO 6</template>
|
||||
<template #content>
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
|
||||
Welcome to XO 6
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-raw-text -->
|
||||
</template>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<template #content> Coming soon</template>
|
||||
<template #content>{{ $t('coming-soon') }}</template>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<DefaultLayout>
|
||||
<template #content> Coming soon</template>
|
||||
<template #content>{{ $t('coming-soon') }}</template>
|
||||
</DefaultLayout>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"@babel/register": "^7.0.0",
|
||||
"@commitlint/cli": "^18.2.0",
|
||||
"@commitlint/config-conventional": "^18.1.0",
|
||||
"@intlify/eslint-plugin-vue-i18n": "^3.0.0",
|
||||
"@limegrass/eslint-plugin-import-alias": "^1.1.0",
|
||||
"@typescript-eslint/parser": "^7.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.12.0",
|
||||
|
||||
92
yarn.lock
92
yarn.lock
@@ -1787,6 +1787,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.14.0":
|
||||
version "7.24.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12"
|
||||
integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.24.0", "@babel/template@^7.3.3":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
|
||||
@@ -2168,6 +2175,21 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/eslintrc@^3.0.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6"
|
||||
integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^10.0.1"
|
||||
globals "^14.0.0"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.2.1"
|
||||
js-yaml "^4.1.0"
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
|
||||
@@ -2268,7 +2290,7 @@
|
||||
source-map-js "^1.0.1"
|
||||
yaml-eslint-parser "^1.2.2"
|
||||
|
||||
"@intlify/core-base@9.13.1":
|
||||
"@intlify/core-base@9.13.1", "@intlify/core-base@^9.12.0":
|
||||
version "9.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.13.1.tgz#bd1f38e665095993ef9b67aeeb794f3cabcb515d"
|
||||
integrity sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==
|
||||
@@ -2276,7 +2298,32 @@
|
||||
"@intlify/message-compiler" "9.13.1"
|
||||
"@intlify/shared" "9.13.1"
|
||||
|
||||
"@intlify/message-compiler@9.13.1", "@intlify/message-compiler@^9.4.0":
|
||||
"@intlify/eslint-plugin-vue-i18n@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/eslint-plugin-vue-i18n/-/eslint-plugin-vue-i18n-3.0.0.tgz#3714d15038b805e3755ef2180e0129ce09cb64ad"
|
||||
integrity sha512-s4fe+VOiqMZGhDrXWnL1xLyHbcFWBcEBeD/KpVrkOtL+utH2LPTi7uZ8RvWSthMS0mUL/7L74hFJ//OUU7AYww==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^3.0.0"
|
||||
"@intlify/core-base" "^9.12.0"
|
||||
"@intlify/message-compiler" "^9.12.0"
|
||||
debug "^4.3.4"
|
||||
eslint-compat-utils "^0.5.0"
|
||||
glob "^10.3.3"
|
||||
globals "^15.0.0"
|
||||
ignore "^5.2.4"
|
||||
import-fresh "^3.3.0"
|
||||
is-language-code "^3.1.0"
|
||||
js-yaml "^4.1.0"
|
||||
json5 "^2.2.3"
|
||||
jsonc-eslint-parser "^2.3.0"
|
||||
lodash "^4.17.21"
|
||||
parse5 "^7.1.2"
|
||||
semver "^7.5.4"
|
||||
synckit "^0.9.0"
|
||||
vue-eslint-parser "^9.3.1"
|
||||
yaml-eslint-parser "^1.2.2"
|
||||
|
||||
"@intlify/message-compiler@9.13.1", "@intlify/message-compiler@^9.12.0", "@intlify/message-compiler@^9.4.0":
|
||||
version "9.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.13.1.tgz#ff8129badf77db3fb648b8d3cceee87c8033ed0a"
|
||||
integrity sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==
|
||||
@@ -10469,6 +10516,11 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb"
|
||||
integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==
|
||||
|
||||
eslint@^8.7.0:
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
|
||||
@@ -10528,6 +10580,15 @@ esniff@^2.0.1:
|
||||
event-emitter "^0.3.5"
|
||||
type "^2.7.2"
|
||||
|
||||
espree@^10.0.1:
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f"
|
||||
integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==
|
||||
dependencies:
|
||||
acorn "^8.11.3"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^4.0.0"
|
||||
|
||||
espree@^9.0.0, espree@^9.3.1, espree@^9.6.0, espree@^9.6.1:
|
||||
version "9.6.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
|
||||
@@ -11920,6 +11981,16 @@ globals@^13.19.0, globals@^13.24.0:
|
||||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globals@^14.0.0:
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
|
||||
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
|
||||
|
||||
globals@^15.0.0:
|
||||
version "15.4.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-15.4.0.tgz#3e36ea6e4d9ddcf1cb42d92f5c4a145a8a2ddc1c"
|
||||
integrity sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==
|
||||
|
||||
globalthis@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
|
||||
@@ -13557,6 +13628,13 @@ is-lambda@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
|
||||
integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
|
||||
|
||||
is-language-code@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-language-code/-/is-language-code-3.1.0.tgz#b2386b49227e7010636f16d0c2c681ca40136ab5"
|
||||
integrity sha512-zJdQ3QTeLye+iphMeK3wks+vXSRFKh68/Pnlw7aOfApFSEIOhYa8P9vwwa6QrImNNBMJTiL1PpYF0f4BxDuEgA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.14.0"
|
||||
|
||||
is-lower-case@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-2.0.2.tgz#1c0884d3012c841556243483aa5d522f47396d2a"
|
||||
@@ -17327,7 +17405,7 @@ parse5-htmlparser2-tree-adapter@^7.0.0:
|
||||
domhandler "^5.0.2"
|
||||
parse5 "^7.0.0"
|
||||
|
||||
parse5@^7.0.0:
|
||||
parse5@^7.0.0, parse5@^7.1.2:
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32"
|
||||
integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==
|
||||
@@ -21321,6 +21399,14 @@ synckit@^0.8.6:
|
||||
"@pkgr/core" "^0.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
synckit@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.0.tgz#5b33b458b3775e4466a5b377fba69c63572ae449"
|
||||
integrity sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==
|
||||
dependencies:
|
||||
"@pkgr/core" "^0.1.0"
|
||||
tslib "^2.6.2"
|
||||
|
||||
syntax-error@^1.1.1:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c"
|
||||
|
||||
Reference in New Issue
Block a user