Les tuiles suivent maintenant les mêmes colSpan × rowSpan que les autres canaux, sur six colonnes — environ 83° d'ouverture, dans le confort du regard — avec un écart serré assumé : espacées, les tuiles se lisent comme des panneaux sans rapport plutôt que comme une planche. Le pas angulaire se déduit de la largeur de cellule et du rayon de l'arc, plutôt que d'être posé en dur. S'y ajoute le sélecteur de langue avec ses drapeaux, et les libellés de l'interface sortis du code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
111 lines
5.2 KiB
C#
111 lines
5.2 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace MyInfoMate.Vr.Ui
|
|
{
|
|
/// <summary>
|
|
/// Les textes de l'app elle-même — « Retour au menu », « Ce contenu est vide » —
|
|
/// par opposition aux textes du contenu, qui viennent de l'export et passent par
|
|
/// <c>ConfigurationExport.Translate</c>.
|
|
///
|
|
/// <b>Pourquoi une table en dur plutôt que le mécanisme du manager.</b> Il y a une
|
|
/// dizaine de phrases, elles ne changent pas avec le contenu, et un casque démarre
|
|
/// souvent sans réseau : les faire venir du serveur ferait dépendre le bouton retour
|
|
/// d'une requête. Le manager, lui, a des centaines de libellés et un back-office pour
|
|
/// les éditer — ce n'est pas le même problème.
|
|
///
|
|
/// Les quatre langues sont celles que le champ <c>languages</c> d'une configuration
|
|
/// propose. Une langue inconnue retombe sur le français plutôt que d'afficher une
|
|
/// clé : un visiteur qui lit la mauvaise langue s'en sort, un visiteur qui lit
|
|
/// <c>backToMenu</c> non.
|
|
/// </summary>
|
|
public static class Strings
|
|
{
|
|
public const string BackToMenu = "backToMenu";
|
|
public const string ChooseLanguage = "chooseLanguage";
|
|
public const string EmptyContent = "emptyContent";
|
|
public const string NothingToday = "nothingToday";
|
|
public const string NotSupported = "notSupported";
|
|
public const string Scene3DFailed = "scene3dFailed";
|
|
|
|
static readonly Dictionary<string, Dictionary<string, string>> Table =
|
|
new Dictionary<string, Dictionary<string, string>>
|
|
{
|
|
["FR"] = new Dictionary<string, string>
|
|
{
|
|
[BackToMenu] = "Retour au menu",
|
|
[ChooseLanguage] = "Choisissez votre langue",
|
|
[EmptyContent] = "Ce contenu est vide.",
|
|
[NothingToday] = "Rien au programme aujourd'hui.",
|
|
[NotSupported] = "Ce type de contenu n'est pas encore affichable dans le casque.",
|
|
[Scene3DFailed] = "Cette scène 3D n'a pas pu être chargée.",
|
|
},
|
|
["EN"] = new Dictionary<string, string>
|
|
{
|
|
[BackToMenu] = "Back to menu",
|
|
[ChooseLanguage] = "Choose your language",
|
|
[EmptyContent] = "This content is empty.",
|
|
[NothingToday] = "Nothing on the programme today.",
|
|
[NotSupported] = "This type of content cannot be shown in the headset yet.",
|
|
[Scene3DFailed] = "This 3D scene could not be loaded.",
|
|
},
|
|
["NL"] = new Dictionary<string, string>
|
|
{
|
|
[BackToMenu] = "Terug naar het menu",
|
|
[ChooseLanguage] = "Kies uw taal",
|
|
[EmptyContent] = "Deze inhoud is leeg.",
|
|
[NothingToday] = "Vandaag staat er niets op het programma.",
|
|
[NotSupported] = "Dit soort inhoud is nog niet zichtbaar in de bril.",
|
|
[Scene3DFailed] = "Deze 3D-scène kon niet worden geladen.",
|
|
},
|
|
["DE"] = new Dictionary<string, string>
|
|
{
|
|
[BackToMenu] = "Zurück zum Menü",
|
|
[ChooseLanguage] = "Wählen Sie Ihre Sprache",
|
|
[EmptyContent] = "Dieser Inhalt ist leer.",
|
|
[NothingToday] = "Heute steht nichts auf dem Programm.",
|
|
[NotSupported] = "Diese Art von Inhalt ist in der Brille noch nicht verfügbar.",
|
|
[Scene3DFailed] = "Diese 3D-Szene konnte nicht geladen werden.",
|
|
},
|
|
};
|
|
|
|
/// <summary>
|
|
/// Le nom d'une langue <b>dans cette langue</b>. C'est la seule façon de nommer un
|
|
/// choix de langue : « Dutch » ne dit rien à quelqu'un qui cherche « Nederlands ».
|
|
/// </summary>
|
|
static readonly Dictionary<string, string> Names = new Dictionary<string, string>
|
|
{
|
|
["FR"] = "Français",
|
|
["EN"] = "English",
|
|
["NL"] = "Nederlands",
|
|
["DE"] = "Deutsch",
|
|
};
|
|
|
|
public const string Fallback = "FR";
|
|
|
|
public static string Get(string key, string language)
|
|
{
|
|
var code = Normalize(language);
|
|
|
|
if (Table.TryGetValue(code, out var texts) && texts.TryGetValue(key, out var text))
|
|
return text;
|
|
|
|
return Table[Fallback][key];
|
|
}
|
|
|
|
/// <summary>Le nom à afficher pour une langue, son code à défaut.</summary>
|
|
public static string NameOf(string language)
|
|
{
|
|
var code = Normalize(language);
|
|
return Names.TryGetValue(code, out var name) ? name : code;
|
|
}
|
|
|
|
/// <summary>
|
|
/// L'export écrit les langues tantôt en <c>fr</c>, tantôt en <c>FR</c> — et les
|
|
/// traductions d'un même contenu ne suivent pas toujours la casse du champ
|
|
/// <c>languages</c> de la configuration. Tout passe par ici.
|
|
/// </summary>
|
|
public static string Normalize(string language) =>
|
|
string.IsNullOrEmpty(language) ? Fallback : language.Trim().ToUpperInvariant();
|
|
}
|
|
}
|