Add Fluent.Net sample to DiscoHawk

This commit is contained in:
YoshiRulz 2025-07-26 12:52:33 +10:00
parent 0dc08f721c
commit ac27453478
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
7 changed files with 182 additions and 0 deletions

View File

@ -3,6 +3,7 @@
<PackageVersion Include="CommunityToolkit.HighPerformance" Version="8.4.0" />
<PackageVersion Include="Cyotek.Drawing.BitmapFont" Version="2.0.4" />
<PackageVersion Include="DotNetAnalyzers.DocumentationAnalyzers" Version="1.0.0-beta.59" />
<PackageVersion Include="Fluent.Net" Version="1.0.63" />
<PackageVersion Include="Google.FlatBuffers" Version="23.5.26" /> <!-- last version with .NET Standard 2.0 support -->
<PackageVersion Include="ImGui.NET" Version="1.90.6.1" />
<PackageVersion Include="JunitXml.TestLogger" Version="3.1.12" />

View File

@ -10,9 +10,11 @@
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Fluent.Net" PrivateAssets="all" />
<ProjectReference Include="$(ProjectDir)../BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj" />
<Content Include="discohawk.ico" />
<EmbeddedResource Include="discohawk.ico" />
<EmbeddedResource Include="locale/*.ftl" />
</ItemGroup>
<ItemGroup>
<Compile Update="About.cs" SubType="Form" />

View File

@ -114,6 +114,8 @@ namespace BizHawk.Client.DiscoHawk
}
}
Sample.RunAll(); // testing Fluent.Net
// Do something for visuals, I guess
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

View File

@ -0,0 +1,101 @@
#nullable enable
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Fluent.Net;
namespace BizHawk.Client.DiscoHawk
{
public sealed class ArgsDict : Dictionary<string, object?>
{
public ArgsDict(int? tabCount = null)
{
Add(nameof(tabCount), tabCount);
}
}
public readonly struct MultiMessageContext
{
private static IReadOnlyList<MessageContext> ReadEmbeddedAndConcat(string lang, MessageContext[] overlays)
{
MessageContext mc = new(lang, new() { UseIsolating = false });
Stream embeddedStream;
try
{
embeddedStream = ReflectionCache.EmbeddedResourceStream($"locale.{lang}.ftl");
}
catch (ArgumentException e)
{
Console.WriteLine(e);
return overlays;
}
using StreamReader sr = new(embeddedStream);
var errors = mc.AddMessages(sr);
foreach (var error in errors) Console.WriteLine(error);
return [ ..overlays, mc ];
}
private readonly IReadOnlyList<MessageContext> _contexts;
public readonly CultureInfo Culture;
public MultiMessageContext(IReadOnlyList<MessageContext> contexts)
{
_contexts = contexts;
Culture = new(_contexts.FirstOrDefault()?.Locales?.First());
}
public MultiMessageContext(string lang, params MessageContext[] overlays)
: this(ReadEmbeddedAndConcat(lang, overlays)) {}
public string? this[string id]
=> GetString(id);
public string? GetString(
string id,
IDictionary<string, object?>? args = null,
ICollection<FluentError>? errors = null)
{
foreach (var context in _contexts)
{
var msg = context.GetMessage(id);
if (msg is not null) return context.Format(msg, args, errors);
}
return null;
}
}
public static class Sample
{
public static void RunAll()
{
static void RunTest(string lang)
{
MultiMessageContext translator = new(lang);
Console.WriteLine($"\n{lang}:");
Console.WriteLine($"tabs-close-button = {translator.GetString("tabs-close-button")}");
Console.WriteLine(
"tabs-close-tooltip ($tabCount = 1) = "
+ translator.GetString("tabs-close-tooltip", new ArgsDict(tabCount: 1)));
Console.WriteLine(
"tabs-close-tooltip ($tabCount = 2) = "
+ translator.GetString("tabs-close-tooltip", new ArgsDict(tabCount: 2)));
Console.WriteLine(
"tabs-close-warning ($tabCount = 1) = "
+ translator.GetString("tabs-close-warning", new ArgsDict(tabCount: 1)));
Console.WriteLine(
"tabs-close-warning ($tabCount = 2) = "
+ translator.GetString("tabs-close-warning", new ArgsDict(tabCount: 2)));
Console.WriteLine($"sync-dialog-title = {translator.GetString("sync-dialog-title")}");
Console.WriteLine($"sync-headline-title = {translator.GetString("sync-headline-title")}");
Console.WriteLine($"sync-signedout-title = {translator.GetString("sync-signedout-title")}");
}
RunTest("en");
RunTest("it");
RunTest("pl");
}
}
}

View File

@ -0,0 +1,24 @@
## Closing tabs
tabs-close-button = Close
tabs-close-tooltip = {$tabCount ->
[one] Close {$tabCount} tab
*[other] Close {$tabCount} tabs
}
tabs-close-warning =
You are about to close {$tabCount} tabs.
Are you sure you want to continue?
## Syncing
-sync-brand-name = Firefox Account
sync-dialog-title = {-sync-brand-name}
sync-headline-title =
{-sync-brand-name}: The best way to bring
your data always with you
sync-signedout-title =
Connect with your {-sync-brand-name}
## Datetime
date-is = The date is 'DATETIME($dt, weekday: "short", month: "short", year: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric")'.

View File

@ -0,0 +1,23 @@
## Closing tabs
tabs-close-button = Chiudi
tabs-close-tooltip = {$tabCount ->
[one] Chiudi {$tabCount} scheda
*[other] Chiudi {$tabCount} schede
}
tabs-close-warning =
Verranno chiuse {$tabCount} schede. Proseguire?
## Syncing
-sync-brand-name = {$first ->
*[uppercase] Account Firefox
[lowercase] account Firefox
}
sync-dialog-title = {-sync-brand-name}
sync-headline-title =
{-sync-brand-name}: il modo migliore
per avere i tuoi dati sempre con te
sync-signedout-title =
Connetti il tuo {-sync-brand-name[lowercase]}

View File

@ -0,0 +1,29 @@
## Closing tabs
tabs-close-button = Zamknij
tabs-close-tooltip = {$tabCount ->
[one] Zamknij kartę
[few] Zamknij {$tabCount} karty
*[many] Zamknij { $tabCount } kart
}
tabs-close-warning = {$tabCount ->
[few] Zostaną zamknięte {$tabCount} karty.
Czy chcesz kontynuować?
*[many] Zostanie zamkniętych {$tabCount} kart.
Czy chcesz kontynuować?
}
## Syncing
-sync-brand-name = {$case ->
*[nominative] Konto Firefox
[genitive] Konta Firefox
[accusative] Kontem Firefox
}
sync-dialog-title = {-sync-brand-name}
sync-headline-title =
{-sync-brand-name}: Najlepszy sposób na to,
aby mieć swoje dane zawsze przy sobie
sync-signedout-title =
Zaloguj do {-sync-brand-name[genitive]}