Add translator web ui

This commit is contained in:
2025-05-16 22:16:11 +02:00
parent f39d936024
commit 218389ae06
18 changed files with 455 additions and 1 deletions

View File

@@ -22,4 +22,4 @@ Console.WriteLine();
var original = translator.TranslateFromPoyo(translated);
Console.WriteLine("Translated back from Poyo:");
Console.WriteLine(original);
Console.WriteLine(original);

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<base href="/"/>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet"/>
<link href=@Assets["_content/MudBlazor/MudBlazor.min.css"] rel="stylesheet"/>
<ImportMap/>
<link rel="icon" type="image/ico" href="favicon.ico"/>
<HeadOutlet @rendermode="InteractiveServer"/>
</head>
<body>
<Routes @rendermode="InteractiveServer"/>
<script src="_framework/blazor.web.js"></script>
<script src=@Assets["_content/MudBlazor/MudBlazor.min.js"]></script>
</body>
</html>

View File

@@ -0,0 +1,101 @@
@inherits LayoutComponentBase
<MudThemeProvider Theme="@_theme" IsDarkMode="_isDarkMode"/>
<MudPopoverProvider/>
<MudDialogProvider/>
<MudSnackbarProvider/>
<MudLayout>
<MudAppBar Elevation="1">
<MudText Typo="Typo.h5" Class="ml-3">PoyoLang</MudText>
<MudSpacer />
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle" />
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Color="Color.Inherit" Edge="Edge.End"
Href="https://git.ilysix.fr/Eveldee/PoyoLang" Target="_blank" />
</MudAppBar>
<MudMainContent Class="pt-16 pa-4">
<MudContainer MaxWidth="MaxWidth.Large">
@Body
</MudContainer>
</MudMainContent>
</MudLayout>
<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
@code {
private bool _drawerOpen = true;
private bool _isDarkMode = true;
private MudTheme? _theme = null;
protected override void OnInitialized()
{
base.OnInitialized();
_theme = new()
{
PaletteLight = _lightPalette,
PaletteDark = _darkPalette,
LayoutProperties = new LayoutProperties()
};
}
private void DrawerToggle()
{
_drawerOpen = !_drawerOpen;
}
private void DarkModeToggle()
{
_isDarkMode = !_isDarkMode;
}
private readonly PaletteLight _lightPalette = new()
{
Black = "#110e2d",
AppbarText = "#424242",
AppbarBackground = "rgba(255,255,255,0.8)",
DrawerBackground = "#ffffff",
GrayLight = "#e8e8e8",
GrayLighter = "#f9f9f9",
};
private readonly PaletteDark _darkPalette = new()
{
Primary = "#7e6fff",
Surface = "#1e1e2d",
Background = "#1a1a27",
BackgroundGray = "#151521",
AppbarText = "#92929f",
AppbarBackground = "rgba(26,26,39,0.8)",
DrawerBackground = "#1a1a27",
ActionDefault = "#74718e",
ActionDisabled = "#9999994d",
ActionDisabledBackground = "#605f6d4d",
TextPrimary = "#b2b0bf",
TextSecondary = "#92929f",
TextDisabled = "#ffffff33",
DrawerIcon = "#92929f",
DrawerText = "#92929f",
GrayLight = "#2a2833",
GrayLighter = "#1e1e2d",
Info = "#4a86ff",
Success = "#3dcb6c",
Warning = "#ffb545",
Error = "#ff3f5f",
LinesDefault = "#33323e",
TableLines = "#33323e",
Divider = "#292838",
OverlayLight = "#1e1e2d80",
};
public string DarkLightModeButtonIcon => _isDarkMode switch
{
true => Icons.Material.Rounded.AutoMode,
false => Icons.Material.Outlined.DarkMode,
};
}

View File

@@ -0,0 +1,19 @@
@page "/counter"
<PageTitle>Counter</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true">Counter</MudText>
<MudText Typo="Typo.body1" Class="mb-4">Current count: @currentCount</MudText>
<MudButton Color="Color.Primary" Variant="Variant.Filled" @onclick="IncrementCount">Click me</MudButton>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

View File

@@ -0,0 +1,38 @@
@page "/Error"
@using System.Diagnostics
<PageTitle>Error</PageTitle>
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
@code{
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
private string? RequestId { get; set; }
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
protected override void OnInitialized() =>
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
}

View File

@@ -0,0 +1,145 @@
@page "/"
@using PoyoLang.Translator
@inject PoyoLangTranslator Translator
@inject IJSRuntime JsRuntime
@inject ISnackbar Snackbar
<PageTitle>Home</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true" Class="mt-5">PoyoLang Translator</MudText>
<MudText Class="mb-5">Using this website you can freely translate from and to the Poyo language.
This language only use variations of the word "poyo" (320 of them!) to write sentences using the latin alphabet.
If you want more information about how this language works and how it is possible to translate to and from it,
check out the <MudLink href="https://git.ilysix.fr/Eveldee/PoyoLang" Target="_blank">source code</MudLink> of this whole project.</MudText>
<MudToggleGroup T="string" @bind-Value="_sourceLanguage" @bind-Value:after="SourceLanguageUpdated"
SelectionMode="SelectionMode.SingleSelection" Color="Color.Primary" CheckMark="true" FixedContent="true"
Class="mb-1" Style="max-width: 30em;">
<MudToggleItem Value="EnglishSourceLanguage" Text="English" />
<MudToggleItem Value="PoyoSourceLanguage" Text="Poyo" />
</MudToggleGroup>
@* Wide screen display *@
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
<MudStack Row="true" StretchItems="StretchItems.StartAndEnd" Class=".d-none .d-md-flex">
<MudStack>
<MudTextField @bind-Value="_sourceText" @bind-Value:after="UpdateTranslatedText" DebounceInterval="500"
Variant="Variant.Outlined" Label="Source text" Lines="15" />
</MudStack>
<MudStack Spacing="1" Row="false">
<MudTooltip Text="Swap languages">
<MudIconButton Icon="@Icons.Material.Filled.SwapHoriz" Color="Color.Primary" OnClick="SwapArrowClicked"/>
</MudTooltip>
<MudTooltip Text="Copy translation result">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Color="Color.Primary" OnClick="CopyResultClicked"/>
</MudTooltip>
<MudTooltip Text="Clear source text">
<MudIconButton Icon="@Icons.Material.Filled.Clear" Color="Color.Error" OnClick="ClearButtonClicked"/>
</MudTooltip>
</MudStack>
<MudStack>
<MudTextField @bind-Value="_translatedText" ReadOnly="true"
Variant="Variant.Outlined" Label="Translation result" Lines="15" />
</MudStack>
</MudStack>
</MudHidden>
@* Mobile display *@
<MudHidden Breakpoint="Breakpoint.MdAndUp">
<MudStack Row="false" StretchItems="StretchItems.StartAndEnd">
<MudStack>
<MudTextField @bind-Value="_sourceText" @bind-Value:after="UpdateTranslatedText" DebounceInterval="500"
Variant="Variant.Outlined" Label="Source text" Lines="15" />
</MudStack>
<MudStack Spacing="1" Row="true">
<MudTooltip Text="Swap languages">
<MudIconButton Icon="@Icons.Material.Filled.SwapHoriz" Color="Color.Primary" OnClick="SwapArrowClicked"/>
</MudTooltip>
<MudTooltip Text="Copy translation result">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" Color="Color.Primary" OnClick="CopyResultClicked"/>
</MudTooltip>
<MudTooltip Text="Clear source text">
<MudIconButton Icon="@Icons.Material.Filled.Clear" Color="Color.Error" OnClick="ClearButtonClicked"/>
</MudTooltip>
</MudStack>
<MudStack>
<MudTextField @bind-Value="_translatedText" ReadOnly="true"
Variant="Variant.Outlined" Label="Translation result" Lines="15" />
</MudStack>
</MudStack>
</MudHidden>
@code {
private const string EnglishSourceLanguage = "English";
private const string PoyoSourceLanguage = "PoyoLang";
private string _sourceText = "";
private string _translatedText = "";
private string _sourceLanguage = EnglishSourceLanguage;
protected override void OnInitialized()
{
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.BottomCenter;
}
private void SourceLanguageUpdated()
{
UpdateTranslatedText();
}
private void SwapArrowClicked()
{
_sourceLanguage = _sourceLanguage switch
{
PoyoSourceLanguage => EnglishSourceLanguage,
_ => PoyoSourceLanguage
};
SwapLanguages();
}
private void SwapLanguages()
{
_sourceText = _translatedText;
UpdateTranslatedText();
}
private void UpdateTranslatedText()
{
string result;
if (_sourceLanguage is PoyoSourceLanguage)
{
result = Translator.TranslateFromPoyo(_sourceText);
}
else
{
result = Translator.TranslateToPoyo(_sourceText);
}
_translatedText = result;
}
private async Task CopyResultClicked()
{
await JsRuntime.InvokeVoidAsync("navigator.clipboard.writeText", _translatedText);
Snackbar.Add("Translation result copied to clipboard!", Severity.Info);
}
private void ClearButtonClicked()
{
_sourceText = string.Empty;
}
}

View File

@@ -0,0 +1,6 @@
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"/>
<FocusOnNavigate RouteData="routeData" Selector="h1"/>
</Found>
</Router>

View File

@@ -0,0 +1,12 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using MudBlazor
@using MudBlazor.Services
@using PoyoLang.Translator.Web
@using PoyoLang.Translator.Web.Components

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>PoyoLang.Translator.Web</RootNamespace>
<Version>0.1.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MudBlazor" Version="8.*"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PoyoLang.Translator\PoyoLang.Translator.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,34 @@
using MudBlazor.Services;
using PoyoLang.Translator;
using PoyoLang.Translator.Web.Components;
var builder = WebApplication.CreateBuilder(args);
// Add MudBlazor services
builder.Services.AddMudServices();
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddSingleton<PoyoLangTranslator>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();

View File

@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5083",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7137;http://localhost:5083",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoyoLang.Translator.SourceG
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoyoLang.Translator", "PoyoLang.Translator\PoyoLang.Translator.csproj", "{079808D0-16FB-4D01-A502-5366018312CB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoyoLang.Translator.Web", "PoyoLang.Translator.Web\PoyoLang.Translator.Web.csproj", "{4620AA2D-D39E-4393-980C-E4DD25E624C3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -36,5 +38,9 @@ Global
{079808D0-16FB-4D01-A502-5366018312CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{079808D0-16FB-4D01-A502-5366018312CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{079808D0-16FB-4D01-A502-5366018312CB}.Release|Any CPU.Build.0 = Release|Any CPU
{4620AA2D-D39E-4393-980C-E4DD25E624C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4620AA2D-D39E-4393-980C-E4DD25E624C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4620AA2D-D39E-4393-980C-E4DD25E624C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4620AA2D-D39E-4393-980C-E4DD25E624C3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

12
docker-publish.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/sh
version=$(grep -oPm1 "(?<=<Version>)[^<]+" PoyoLang.Translator.Web/PoyoLang.Translator.Web.csproj)
dotnet.exe publish PoyoLang.Translator.Web \
-c Release \
-r linux-x64 \
-p:PublishProfile=DefaultContainer \
-p:InvariantGlobalization=true \
-p:ContainerFamily=alpine \
-p:ContainerRegistry=git.ilysix.fr \
-p:ContainerRepository=Eveldee/PoyoLang \
-p:ContainerImageTags="\"$version;latest\""