i18n: pass all visible UI strings through t() — no more hardcoded labels

Move Link, GW, LXC, VM chip tags, WAN labels, form placeholders, and
confirm-dialog delete verbs into i18n.js for all three locales (fr/en/es).
confirmDeleteDevice and confirmDeleteNetwork now include the action verb
so the JS callers no longer hardcode "Supprimer".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 18:31:31 +02:00
parent de03e38a3c
commit 41cd9c096c
4 changed files with 43 additions and 19 deletions
+4 -4
View File
@@ -142,7 +142,7 @@
<span v-if="iface.vlan_id" class="iface-vlan" :style="{ background: vlanColor(iface.vlan_id) }">
{{ vlanLabel(iface.vlan_id) }}
</span>
<span v-if="iface.is_upstream" class="iface-upstream"> WAN</span>
<span v-if="iface.is_upstream" class="iface-upstream">{{ t('wanUpstreamTag') }}</span>
</div>
</div>
</div>
@@ -156,7 +156,7 @@
<div class="fields-row">
<div class="field">
<label>{{ t('fieldName') }}</label>
<input v-model="form.name" type="text" required placeholder="ex: srv-web-01" />
<input v-model="form.name" type="text" required :placeholder="t('deviceNamePlaceholder')" />
</div>
<div class="field">
<label>{{ t('fieldType') }}</label>
@@ -213,7 +213,7 @@
</select>
<label class="iface-upstream">
<input type="checkbox" v-model="iface.is_upstream" />
<span>WAN</span>
<span>{{ t('wanLabel') }}</span>
</label>
<button type="button" class="btn-rm-iface" @click="removeInterface(idx)"></button>
</div>
@@ -434,7 +434,7 @@ async function save() {
}
async function remove(device) {
if (!confirm(`Supprimer ${tFmt('confirmDeleteDevice', device.name)}`)) return
if (!confirm(tFmt('confirmDeleteDevice', device.name))) return
try {
await devicesApi.remove(device.id)
emit('refresh')
+7 -7
View File
@@ -32,7 +32,7 @@
<svg v-for="b in detectBrands(d.name, d.description)" :key="b.title" width="11" height="11" viewBox="0 0 24 24" fill="currentColor" class="chip-brand-icon" :title="b.title" :style="{ color: '#' + b.hex }"><path :d="b.path" /></svg>
</div>
</div>
<a v-if="d.url" :href="d.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">Link</a>
<a v-if="d.url" :href="d.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">{{ t('tagLink') }}</a>
<span v-if="pingStatus[d.id]" class="ping-dot" :class="'ping-' + pingStatus[d.id]" :title="pingStatus[d.id] === 'up' ? t('reachable') : t('unreachable')"></span>
</div>
</div>
@@ -53,7 +53,7 @@
<svg v-for="b in detectBrands(d.name, d.description)" :key="b.title" width="11" height="11" viewBox="0 0 24 24" fill="currentColor" class="chip-brand-icon" :title="b.title" :style="{ color: '#' + b.hex }"><path :d="b.path" /></svg>
</div>
</div>
<a v-if="d.url" :href="d.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">Link</a>
<a v-if="d.url" :href="d.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">{{ t('tagLink') }}</a>
<span v-if="pingStatus[d.id]" class="ping-dot" :class="'ping-' + pingStatus[d.id]" :title="pingStatus[d.id] === 'up' ? t('reachable') : t('unreachable')"></span>
</div>
</div>
@@ -101,10 +101,10 @@
</div>
<div class="chip-tags">
<span v-if="pingStatus[item.device.id]" class="ping-dot" :class="'ping-' + pingStatus[item.device.id]" :title="pingStatus[item.device.id] === 'up' ? t('reachable') : t('unreachable')"></span>
<a v-if="item.device.url" :href="item.device.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">Link</a>
<span v-if="item.device.is_gateway" class="chip-tag tag-gw">GW</span>
<span v-if="item.device.virt_type === 'lxc'" class="chip-tag tag-lxc">LXC</span>
<span v-if="item.device.virt_type === 'qemu'" class="chip-tag tag-vm">VM</span>
<a v-if="item.device.url" :href="item.device.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">{{ t('tagLink') }}</a>
<span v-if="item.device.is_gateway" class="chip-tag tag-gw">{{ t('tagGw') }}</span>
<span v-if="item.device.virt_type === 'lxc'" class="chip-tag tag-lxc">{{ t('tagLxc') }}</span>
<span v-if="item.device.virt_type === 'qemu'" class="chip-tag tag-vm">{{ t('tagVm') }}</span>
</div>
</div>
</div>
@@ -139,7 +139,7 @@
<svg v-for="b in detectBrands(d.name, d.description)" :key="b.title" width="11" height="11" viewBox="0 0 24 24" fill="currentColor" class="chip-brand-icon" :title="b.title" :style="{ color: '#' + b.hex }"><path :d="b.path" /></svg>
</div>
</div>
<a v-if="d.url" :href="d.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">Link</a>
<a v-if="d.url" :href="d.url" target="_blank" rel="noreferrer noopener" class="chip-tag tag-link" :title="t('openWebUI')">{{ t('tagLink') }}</a>
<span v-if="pingStatus[d.id]" class="ping-dot" :class="'ping-' + pingStatus[d.id]" :title="pingStatus[d.id] === 'up' ? t('reachable') : t('unreachable')"></span>
</div>
</div>
+2 -2
View File
@@ -51,7 +51,7 @@
</div>
<div class="field">
<label>{{ t('fieldName') }}</label>
<input v-model="form.name" type="text" required placeholder="ex: Serveurs" />
<input v-model="form.name" type="text" required :placeholder="t('networkNamePlaceholder')" />
</div>
<div class="field">
<label>{{ t('subnet') }}</label>
@@ -154,7 +154,7 @@ function _affectedCount(vlan) {
async function remove(vlan) {
const label = vlan.vlan_id != null ? `VLAN ${vlan.vlan_id}${vlan.name}` : `LAN ${vlan.name}`
const count = _affectedCount(vlan)
let msg = `Supprimer ${tFmt('confirmDeleteNetwork', label)}`
let msg = tFmt('confirmDeleteNetwork', label)
if (count > 0) msg += '\n' + tFmt('confirmDeleteNetworkHosts', count)
if (!confirm(msg)) return
try {
+30 -6
View File
@@ -36,6 +36,10 @@ const LANGS = {
reachable: 'Joignable',
unreachable: 'Injoignable',
openWebUI: "Ouvrir l'interface web",
tagLink: 'Link',
tagGw: 'GW',
tagLxc: 'LXC',
tagVm: 'VM',
// DeviceManager
devices: 'Équipements',
addDevice: '+ Ajouter un équipement',
@@ -68,12 +72,16 @@ const LANGS = {
create: 'Créer',
badgeGateway: 'Passerelle',
badgeLivebox: 'Livebox',
confirmDeleteDevice: '{0} et tous ses liens ?',
confirmDeleteNetwork: '{0} ?',
confirmDeleteDevice: 'Supprimer {0} et tous ses liens ?',
confirmDeleteNetwork: 'Supprimer {0} ?',
confirmDeleteNetworkHosts: '{0} équipement(s) hors passerelle seront également supprimés.',
saveError: 'Erreur lors de la sauvegarde',
deleteError: 'Erreur lors de la suppression',
descPlaceholder: 'Rôle, OS, notes…',
wanLabel: 'WAN',
wanUpstreamTag: '↑ WAN',
deviceNamePlaceholder: 'ex: srv-web-01',
networkNamePlaceholder: 'ex: Serveurs',
// Device types
typeServer: 'Serveur',
typeSwitch: 'Switch',
@@ -201,6 +209,10 @@ const LANGS = {
reachable: 'Reachable',
unreachable: 'Unreachable',
openWebUI: 'Open web interface',
tagLink: 'Link',
tagGw: 'GW',
tagLxc: 'LXC',
tagVm: 'VM',
devices: 'Devices',
addDevice: '+ Add device',
noDevicesConfigured: 'No devices configured. Start by adding one.',
@@ -232,12 +244,16 @@ const LANGS = {
create: 'Create',
badgeGateway: 'Gateway',
badgeLivebox: 'ISP Box',
confirmDeleteDevice: '{0} and all its links?',
confirmDeleteNetwork: '{0}?',
confirmDeleteDevice: 'Delete {0} and all its links?',
confirmDeleteNetwork: 'Delete {0}?',
confirmDeleteNetworkHosts: '{0} non-gateway device(s) will also be deleted.',
saveError: 'Error while saving',
deleteError: 'Error while deleting',
descPlaceholder: 'Role, OS, notes…',
wanLabel: 'WAN',
wanUpstreamTag: '↑ WAN',
deviceNamePlaceholder: 'e.g. srv-web-01',
networkNamePlaceholder: 'e.g. Servers',
typeServer: 'Server',
typeSwitch: 'Switch',
typeRouter: 'Router',
@@ -361,6 +377,10 @@ const LANGS = {
reachable: 'Alcanzable',
unreachable: 'No alcanzable',
openWebUI: 'Abrir interfaz web',
tagLink: 'Link',
tagGw: 'GW',
tagLxc: 'LXC',
tagVm: 'VM',
devices: 'Equipos',
addDevice: '+ Añadir equipo',
noDevicesConfigured: 'No hay equipos configurados. Empiece añadiendo uno.',
@@ -392,12 +412,16 @@ const LANGS = {
create: 'Crear',
badgeGateway: 'Pasarela',
badgeLivebox: 'Router ISP',
confirmDeleteDevice: '{0} y todos sus enlaces?',
confirmDeleteNetwork: '{0}?',
confirmDeleteDevice: 'Eliminar {0} y todos sus enlaces?',
confirmDeleteNetwork: 'Eliminar {0}?',
confirmDeleteNetworkHosts: '{0} equipo(s) no gateway también serán eliminados.',
saveError: 'Error al guardar',
deleteError: 'Error al eliminar',
descPlaceholder: 'Rol, SO, notas…',
wanLabel: 'WAN',
wanUpstreamTag: '↑ WAN',
deviceNamePlaceholder: 'ej: srv-web-01',
networkNamePlaceholder: 'ej: Servidores',
typeServer: 'Servidor',
typeSwitch: 'Switch',
typeRouter: 'Router',