Files
CodeNomad/packages/ui/src/lib/i18n/messages/fr/remoteAccess.ts
VooDisss f3c54df283 fix(server): show sane remote URLs for 0.0.0.0 binds (#262)
Closes #261

## Summary

- improve startup remote URL selection when the server binds to
`0.0.0.0`
- print additional reachable remote URLs instead of advertising only the
first external address
- add targeted tests for address ordering and advertisability behavior

## Problem

When CodeNomad was started with `--host 0.0.0.0`, the CLI chose the
first external IPv4 address it discovered and displayed only that one as
the remote URL.

On Windows machines with WSL, Hyper-V, Docker, or other virtual
adapters, that often surfaced a virtual `172.x.x.x` address even though
a more useful LAN address such as `192.168.x.x` was also reachable and
usable from other devices.

That made remote access look broken or confusing even though the server
itself was accessible.

## What changed

- reuse the resolved network-address list for both:
  - primary remote URL selection
  - startup logging of additional reachable URLs
- choose the primary remote URL from the **advertisable** external
addresses instead of any external address
- print `Other Accessible URLs` when multiple useful remote URLs are
available
- avoid hard-coding a preference like `192.168 > 10 > 172`
- suppress link-local `169.254.*` addresses from user-facing advertised
URLs
- add tests covering:
  - stable ordering across RFC1918 address ranges
  - link-local addresses being non-advertisable
  - link-local-first discovery not stealing the primary LAN URL

## Why this approach

This keeps address derivation in the network-address resolver layer and
limits `index.ts` to startup wiring and presentation.

It also fixes the misleading terminal output without redesigning binding
behavior, TLS behavior, or the server API contract.

## Validation

- `npm run typecheck --workspace @neuralnomads/codenomad`
- `npx tsx --test
'.\\src\\server\\__tests__\\network-addresses.test.ts'`

## Notes

- this change is intentionally focused on selection and presentation of
reachable addresses
- it does not attempt a broader virtual-adapter classification policy
beyond suppressing clearly low-value link-local addresses in user-facing
output

---------

Co-authored-by: Shantur Rathore <i@shantur.com>
2026-04-01 22:12:28 +01:00

54 lines
3.8 KiB
TypeScript

export const remoteAccessMessages = {
"remoteAccess.eyebrow": "Passation à distance",
"remoteAccess.title": "Se connecter à CodeNomad à distance",
"remoteAccess.subtitle": "Utilisez les adresses ci-dessous pour ouvrir CodeNomad depuis un autre appareil.",
"remoteAccess.close": "Fermer l'accès à distance",
"remoteAccess.refresh": "Rafraîchir",
"remoteAccess.sections.listeningMode.label": "Mode d'écoute",
"remoteAccess.sections.listeningMode.help": "Autorisez ou limitez les passations à distance en écoutant sur toutes les interfaces ou uniquement sur localhost.",
"remoteAccess.toggle.on": "Activé",
"remoteAccess.toggle.off": "Désactivé",
"remoteAccess.toggle.title": "Autoriser les connexions depuis d'autres IP",
"remoteAccess.toggle.caption.all": "Écoute sur 0.0.0.0",
"remoteAccess.toggle.caption.local": "Écoute sur 127.0.0.1",
"remoteAccess.toggle.note": "Modifier ceci nécessite un redémarrage et stoppe temporairement toutes les instances actives. Partagez les adresses ci-dessous une fois le serveur redémarré.",
"remoteAccess.listeningMode.restartConfirm.message": "Redémarrer pour appliquer le mode d'écoute ? Cela arrêtera toutes les instances en cours.",
"remoteAccess.listeningMode.restartConfirm.title.all": "Ouvrir aux autres appareils",
"remoteAccess.listeningMode.restartConfirm.title.local": "Limiter à cet appareil",
"remoteAccess.listeningMode.restartConfirm.confirmLabel": "Redémarrer maintenant",
"remoteAccess.listeningMode.restartConfirm.cancelLabel": "Annuler",
"remoteAccess.restart.errorManual": "Impossible de redémarrer automatiquement. Veuillez redémarrer l'application pour appliquer le changement.",
"remoteAccess.sections.serverPassword.label": "Mot de passe du serveur",
"remoteAccess.sections.serverPassword.help": "Les passations à distance nécessitent un mot de passe. Définissez-en un facile à retenir pour autoriser la connexion depuis d'autres appareils.",
"remoteAccess.authStatus.unavailable": "Statut d'authentification indisponible.",
"remoteAccess.username": "Nom d'utilisateur : {username}",
"remoteAccess.password.status.set": "Un mot de passe est défini pour l'accès à distance.",
"remoteAccess.password.status.unset": "Aucun mot de passe mémorable n'est encore défini. Définissez-en un pour autoriser les connexions à distance.",
"remoteAccess.password.actions.cancel": "Annuler",
"remoteAccess.password.actions.change": "Changer le mot de passe",
"remoteAccess.password.actions.set": "Définir le mot de passe",
"remoteAccess.password.form.newPassword": "Nouveau mot de passe",
"remoteAccess.password.form.confirmPassword": "Confirmer le mot de passe",
"remoteAccess.password.form.placeholder": "Au moins 8 caractères",
"remoteAccess.password.error.tooShort": "Le mot de passe doit contenir au moins 8 caractères.",
"remoteAccess.password.error.mismatch": "Les mots de passe ne correspondent pas.",
"remoteAccess.password.save.saving": "Enregistrement…",
"remoteAccess.password.save.label": "Enregistrer le mot de passe",
"remoteAccess.sections.addresses.label": "Adresses accessibles",
"remoteAccess.sections.addresses.help": "Lancez ou scannez depuis une autre machine pour passer le contrôle.",
"remoteAccess.addresses.loading": "Chargement des adresses…",
"remoteAccess.addresses.none": "Aucune adresse disponible pour le moment.",
"remoteAccess.addresses.actions.showOther": "Afficher {count} autres adresses",
"remoteAccess.addresses.actions.hideOther": "Masquer les autres adresses",
"remoteAccess.address.scope.network": "Réseau",
"remoteAccess.address.scope.loopback": "Boucle locale",
"remoteAccess.address.scope.internal": "Interne",
"remoteAccess.address.open": "Ouvrir",
"remoteAccess.address.showQr": "Afficher le QR",
"remoteAccess.address.hideQr": "Masquer le QR",
"remoteAccess.address.qrAlt": "QR pour {url}",
} as const