Files
Ilker ManapandClaude Opus 5.5 11231d8c2b The portal in English and Turkish: a catalogue per language, a switcher at the foot of every page, landing.language, Turkish numbers and dates
Every template and handler message in internal/web goes through a JSON
catalogue under internal/web/locales/<code>/, with English as the fallback.
The language is the person's choice (a cookie set by /_lang/{code}), else
Accept-Language, else landing.language. Tests refuse a key some language
lacks, a translation with other arguments than English, and template text
left in English.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 00:12:53 +02:00

54 lines
2.6 KiB
HTML

{{define "nvlink"}}<!doctype html>
<html lang="{{lang}}"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="refresh" content="30">
<title>{{t "nvlink.title"}} · llmgw</title><link rel="stylesheet" href="{{stylesheet}}">
</head><body><div class="wrap wide">
<header>
<h1>{{t "nvlink.title"}}</h1>
<p class="sub">{{tn "nvlink.sub" (len .Domains)}}</p>
{{if .OnAdminListener}}<nav><a href="/">{{t "node.nav.cluster"}}</a></nav>{{else}}{{template "nav" .Nav}}{{end}}
</header>
{{if not .Domains}}
<p class="empty">{{t "nvlink.empty"}}</p>
{{end}}
<div class="racks">
{{range .Domains}}
<section class="rack{{if .Problems}} troubled{{end}}">
<header class="rack-head">
<div><h2>{{.Short}}</h2><p class="note"><code>{{.ClusterUUID}}</code> · {{t "nvlink.clique" .CliqueID}}</p></div>
<div class="rack-stats">
<div><b>{{.Usable}}/{{len .Members}}</b><span>{{t "nvlink.trays_usable"}}</span></div>
<div><b>{{.Joined}}/{{.GPUs}}</b><span>{{t "nvlink.gpus_joined"}}</span></div>
</div>
</header>
<div class="rack-body">
<div class="nvswitch"><span translate="no">NVLink Switch</span><i></i></div>
<div class="rack-trays">
<div class="backplane" aria-hidden="true"></div>
{{range .Members}}
<div class="tray{{if not .Usable}} out{{end}}">
<a class="tray-name" href="{{$.Nodes}}/{{.Node}}">{{.Node}}</a>
{{/* A GPU's fabric state and bandwidth are the driver's words. */}}
<div class="chips">{{range .GPUs}}<span class="gpu-chip{{if .Joined}} joined{{else}} lost{{end}}{{if and .Bandwidth (ne .Bandwidth "Full")}} slow{{end}}"
title="GPU {{.Index}} · {{.Name}} · {{or .State (t "nvlink.no_fabric")}}{{if .Bandwidth}} · {{t "node.gpu.bandwidth" .Bandwidth}}{{end}}">{{.Index}}</span>{{end}}</div>
<span class="imex{{if and (eq .IMEX "active") .IMEXChannels}} up{{end}}" title="{{t "nvlink.imex" (or .IMEX (t "node.imex.not_installed")) .IMEXChannels}}" translate="no">IMEX</span>
</div>
{{end}}
</div>
</div>
{{/* The level is a class and a word; the message is the NVLink checker's
own, in English. */}}
{{if .Problems}}<ul class="fabric-problems rack-problems">{{range .Problems}}
<li class="{{.Level}}"><span class="tag{{if eq (printf "%s" .Level) "fail"}} bad{{end}}">{{t (print "fabric.level." .Level)}}</span> {{.Message}}</li>{{end}}</ul>{{end}}
</section>
{{end}}
</div>
<p class="note">{{t "nvlink.note"}}</p>
<footer><span>llmgw {{.Version}} · {{t "common.refreshes_every" 30}}</span><span>{{.Now}}</span>{{template "langs"}}</footer>
</div></body></html>{{end}}