From f930d9e408ad5b4c9fd7da13a614f48fc2e0f8d2 Mon Sep 17 00:00:00 2001 From: LD-Reborn Date: Sat, 29 Nov 2025 22:34:54 +0100 Subject: [PATCH] Added localization --- OneForMe.csproj | 1 + Program.cs | 17 +++ Resources/SharedResources.de.resx | 234 ++++++++++++++++++++++++++++++ Resources/SharedResources.en.resx | 234 ++++++++++++++++++++++++++++++ Services/LocalizationService.cs | 17 +++ Views/Home/Dashboard.cshtml | 60 ++++---- Views/Order/Create.cshtml | 31 ++-- Views/Order/Details.cshtml | 49 ++++--- Views/Order/Join.cshtml | 53 +++---- 9 files changed, 605 insertions(+), 91 deletions(-) create mode 100644 Resources/SharedResources.de.resx create mode 100644 Resources/SharedResources.en.resx create mode 100644 Services/LocalizationService.cs diff --git a/OneForMe.csproj b/OneForMe.csproj index caa42a5..dbf48b5 100644 --- a/OneForMe.csproj +++ b/OneForMe.csproj @@ -16,6 +16,7 @@ + diff --git a/Program.cs b/Program.cs index 5ac7f84..c939daa 100644 --- a/Program.cs +++ b/Program.cs @@ -1,6 +1,9 @@ using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Localization; using Microsoft.EntityFrameworkCore; using OneForMe.Data; +using OneForMe.Services; +using System.Globalization; var builder = WebApplication.CreateBuilder(args); @@ -8,6 +11,16 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddControllersWithViews(); +// Add Localization +builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); +builder.Services.Configure(options => +{ + var supportedCultures = new[] { new CultureInfo("en"), new CultureInfo("de") }; + options.DefaultRequestCulture = new RequestCulture("en"); + options.SupportedCultures = supportedCultures; + options.SupportedUICultures = supportedCultures; +}); + // Add Swagger/OpenAPI builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(options => @@ -37,6 +50,9 @@ builder.Services.AddIdentity(options => .AddEntityFrameworkStores() .AddDefaultTokenProviders(); +// Add LocalizationService +builder.Services.AddScoped(); + var app = builder.Build(); // Create and migrate database on startup @@ -64,6 +80,7 @@ if (!app.Environment.IsDevelopment()) } app.UseHttpsRedirection(); +app.UseRequestLocalization(); app.UseRouting(); app.UseAuthentication(); diff --git a/Resources/SharedResources.de.resx b/Resources/SharedResources.de.resx new file mode 100644 index 0000000..a9fd1d9 --- /dev/null +++ b/Resources/SharedResources.de.resx @@ -0,0 +1,234 @@ + + + + Willkommen bei OneForMe + + + Angemeldet als + + + Abmelden + + + Bestellung erstellen + + + Bestellname + + + Geben Sie den Bestellnamen ein + + + Beschreibung + + + Geben Sie eine Beschreibung ein (optional) + + + Restaurant + + + Geben Sie den Restaurantnamen ein + + + Artikelname + + + Preis + + + Entfernen + + + Artikel hinzufügen + + + Abbrechen + + + Neue Bestellung erstellen + + + Starten Sie eine neue Gruppenbestellung und laden Sie Freunde ein + + + Bestellung beitreten + + + Treten Sie einer bestehenden Bestellung mit dem Bestellcode bei + + + Bestellcode eingeben + + + Beitreten + + + Meine Bestellungen + + + Bestellungen, denen ich beigetreten bin + + + Sie haben noch keine Bestellungen erstellt. + + + Sie sind noch keiner Bestellung beigetreten. + + + Ansicht + + + Bestellung abschließen + + + Abgeschlossen + + + Code + + + Erstellt von + + + Artikel + + + Bestellungen + + + Gesamt + + + Ich schulde + + + Mehr hinzufügen + + + Status + + + Offen + + + Menüpunkte + + + Artikel + + + Preis + + + Noch keine Artikel hinzugefügt + + + Teilnehmer + + + Menge + + + Noch keine Bestellungen + + + Bestellung teilen + + + Senden Sie diesen Link an andere: + + + Kopieren + + + Schnellstatistiken + + + Gesamtartikel + + + Gesamtbestellungen + + + Gesamtumsatz + + + Link in die Zwischenablage kopiert! + + + Bestellungen, denen ich beigetreten bin + + + Ihr Name + + + Geben Sie Ihren Namen ein + + + Ihre E-Mail (optional) + + + Geben Sie Ihre E-Mail ein + + + Artikel auswählen + + + Wählen Sie einen Artikel + + + Zur Bestellung hinzufügen + + + Zurück zum Dashboard + + + Keine Artikel verfügbar für diese Bestellung + + + Aktuelle Bestellungen + + + Person + + + schuldet + + + Bestellsumme + + + Restaurantname + + + Geben Sie den Restaurantnamen ein + + + Beschreibung + + + Geben Sie eine Beschreibung ein (optional) + + + Artikel-Name + + + Geben Sie den Artikelnamen ein + + + Artikel hinzufügen + + + Abbrechen + + + Entfernen + + + Geben Sie Ihrer Bestellung einen Namen + + + Fügen Sie Artikel hinzu, die Menschen bestellen können + + \ No newline at end of file diff --git a/Resources/SharedResources.en.resx b/Resources/SharedResources.en.resx new file mode 100644 index 0000000..2a91762 --- /dev/null +++ b/Resources/SharedResources.en.resx @@ -0,0 +1,234 @@ + + + + Welcome to OneForMe + + + Logged in as + + + Logout + + + Create Order + + + Order Name + + + Enter order name + + + Description + + + Enter a description (optional) + + + Restaurant + + + Enter restaurant name + + + Item Name + + + Price + + + Remove + + + Add Item + + + Cancel + + + Create New Order + + + Start a new group order and invite friends + + + Join Order + + + Join an existing order using the order code + + + Enter order code + + + Join + + + My Orders + + + Orders I Joined + + + You haven't created any orders yet. + + + You haven't joined any orders yet. + + + View + + + Close Order + + + Closed + + + Code + + + Created by + + + Items + + + Orders + + + Total + + + I owe + + + Add More + + + Status + + + Open + + + Menu Items + + + Item + + + Price + + + No items added yet + + + Participant + + + Qty + + + No orders yet + + + Share Order + + + Send this link to others: + + + Copy + + + Quick Stats + + + Total Items + + + Total Orders + + + Total Revenue + + + Link copied to clipboard! + + + Orders I joined + + + Your Name + + + Enter your name + + + Your Email (optional) + + + Enter your email + + + Select Item + + + Choose an item + + + Add to Order + + + Back to Dashboard + + + No items available for this order + + + Current Orders + + + Person + + + Owes + + + Order Total + + + Restaurant Name + + + Enter restaurant name + + + Description + + + Enter a description (optional) + + + Item Name + + + Enter item name + + + Add Menu Item + + + Cancel + + + Remove + + + Give your order a name + + + Add items that people can order + + \ No newline at end of file diff --git a/Services/LocalizationService.cs b/Services/LocalizationService.cs new file mode 100644 index 0000000..c47286c --- /dev/null +++ b/Services/LocalizationService.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Localization; + +namespace OneForMe.Services; + +public class LocalizationService +{ + private readonly IStringLocalizer _localizer; + + public LocalizationService(IStringLocalizerFactory factory) + { + _localizer = factory.Create("SharedResources", "OneForMe"); + } + + public string Get(string key) => _localizer[key]; + + public string this[string key] => _localizer[key]; +} \ No newline at end of file diff --git a/Views/Home/Dashboard.cshtml b/Views/Home/Dashboard.cshtml index 32899f1..6ac5c5a 100644 --- a/Views/Home/Dashboard.cshtml +++ b/Views/Home/Dashboard.cshtml @@ -1,16 +1,18 @@ -@using OneForMe.Controllers +@using Microsoft.AspNetCore.Localization +@using OneForMe.Services +@inject LocalizationService Localizer @model DashboardViewModel @{ - ViewData["Title"] = "Dashboard"; + ViewData["Title"] = Localizer.Get("Welcome"); }
-

Welcome to OneForMe

-

Logged in as: @User.Identity?.Name

- Logout +

@Localizer.Get("Welcome")

+

@Localizer.Get("LoggedInAs"): @User.Identity?.Name

+ @Localizer.Get("Logout")
@@ -18,9 +20,9 @@
-
Create New Order
-

Start a new group order and invite friends

- Create Order +
@Localizer.Get("CreateNewOrder")
+

@Localizer.Get("StartGroupOrder")

+ @Localizer.Get("CreateNewOrder")
@@ -28,12 +30,12 @@
-
Join Order
-

Join an existing order using the order code

+
@Localizer.Get("JoinOrder")
+

@Localizer.Get("JoinExistingOrder")

- - + +
@@ -46,7 +48,7 @@
-

My Created Orders

+

@Localizer.Get("MyCreatedOrders")

@if (Model.CreatedOrders.Any()) {
@@ -57,20 +59,20 @@
@order.CreatorName

- Code: @order.OrderCode
- Created: @order.CreatedAt.ToString("MMM dd, yyyy HH:mm")
- Items: @order.MenuItems.Count | Orders: @order.OrderItems.Count + @Localizer.Get("Code"): @order.OrderCode
+ @Localizer.Get("Created"): @order.CreatedAt.ToString("MMM dd, yyyy HH:mm")
+ @Localizer.Get("Items"): @order.MenuItems.Count | @Localizer.Get("Orders"): @order.OrderItems.Count

-

Total: $@order.OrderItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

+

@Localizer.Get("Total"): $@order.OrderItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

- View + @Localizer.Get("View") @if (!order.IsClosed) { - Close Order + @Localizer.Get("CloseOrder") } else { - Closed + @Localizer.Get("Closed") }
@@ -81,7 +83,7 @@ } else { -
You haven't created any orders yet.
+
@Localizer.Get("NoCreatedOrders")
}
@@ -91,7 +93,7 @@
-

Orders I Joined

+

@Localizer.Get("OrdersIJJoined")

@if (Model.JoinedOrders.Any()) {
@@ -103,16 +105,16 @@
@order.CreatorName

- Code: @order.OrderCode
- Created by: @order.CreatorName
- My items: @myItems.Count + @Localizer.Get("Code"): @order.OrderCode
+ @Localizer.Get("CreatedBy"): @order.CreatorName
+ @Localizer.Get("MyItems"): @myItems.Count

-

I owe: $@myItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

+

@Localizer.Get("IOwe"): $@myItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

@@ -123,7 +125,7 @@ } else { -
You haven't joined any orders yet.
+
@Localizer.Get("NoJoinedOrders")
}
diff --git a/Views/Order/Create.cshtml b/Views/Order/Create.cshtml index 30115fa..849d21f 100644 --- a/Views/Order/Create.cshtml +++ b/Views/Order/Create.cshtml @@ -1,5 +1,8 @@ +@using OneForMe.Services +@inject LocalizationService Localizer + @{ - ViewData["Title"] = "Create Order"; + ViewData["Title"] = Localizer["CreateOrder"]; }
@@ -7,43 +10,43 @@
-

Create New Order

+

@Localizer["CreateNewOrder"]

- + - Give your order a name + @Localizer["GiveOrderName"]

-
Menu Items
-

Add items that people can order

+
@Localizer["MenuItems"]
+

@Localizer["AddItemsThatPeopleCanOrder"]

- +
$ - +
- +
- - Cancel + + @Localizer["Cancel"]
@@ -60,13 +63,13 @@ document.getElementById('addItemBtn').addEventListener('click', function() { newRow.innerHTML = `
- +
$ - - + +
diff --git a/Views/Order/Details.cshtml b/Views/Order/Details.cshtml index ef9da39..51b94c5 100644 --- a/Views/Order/Details.cshtml +++ b/Views/Order/Details.cshtml @@ -1,7 +1,10 @@ +@using Microsoft.AspNetCore.Localization +@using OneForMe.Services +@inject LocalizationService Localizer @model OneForMe.Models.Order @{ - ViewData["Title"] = "Order Details"; + ViewData["Title"] = Model.CreatorName; }
@@ -10,15 +13,15 @@

@Model.CreatorName

-

Order Code: @Model.OrderCode

-

Created by: @Model.CreatorName

-

Status: @(Model.IsClosed ? "Closed" : "Open")

+

@Localizer.Get("Code"): @Model.OrderCode

+

@Localizer.Get("CreatedBy"): @Model.CreatorName

+

@Localizer.Get("Status"): @(Model.IsClosed ? Localizer.Get("Closed") : Localizer.Get("Open"))

-
Menu Items
+
@Localizer.Get("MenuItems")
@if (Model.MenuItems.Any()) @@ -26,8 +29,8 @@ - - + + @@ -43,14 +46,14 @@ } else { -

No items added yet

+

@Localizer.Get("NoItemsAdded")

}
-
Orders (@Model.OrderItems.Count)
+
@Localizer.Get("Orders") (@Model.OrderItems.Count)
@if (Model.OrderItems.Any()) @@ -58,10 +61,10 @@
ItemPrice@Localizer.Get("Item")@Localizer.Get("Price")
- - - - + + + + @@ -79,7 +82,7 @@ } else { -

No orders yet

+

@Localizer.Get("NoOrdersYet")

} @@ -88,27 +91,27 @@
-
Share Order
-

Send this link to others:

+
@Localizer.Get("ShareOrder")
+

@Localizer.Get("SendLinkToOthers")

- +
-
Quick Stats
-

Total Items: @Model.MenuItems.Count

-

Total Orders: @Model.OrderItems.Count

-

Total Revenue: $@Model.OrderItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

+
@Localizer.Get("QuickStats")
+

@Localizer.Get("TotalItems"): @Model.MenuItems.Count

+

@Localizer.Get("TotalOrders"): @Model.OrderItems.Count

+

@Localizer.Get("TotalRevenue"): $@Model.OrderItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

@if (!Model.IsClosed) { - Close Order + @Localizer.Get("CloseOrder") }
@@ -119,6 +122,6 @@ function copyToClipboard() { const link = document.getElementById('shareLink'); link.select(); document.execCommand('copy'); - alert('Link copied to clipboard!'); + alert('@Localizer.Get("LinkCopied")'); } \ No newline at end of file diff --git a/Views/Order/Join.cshtml b/Views/Order/Join.cshtml index 975c57f..2afa164 100644 --- a/Views/Order/Join.cshtml +++ b/Views/Order/Join.cshtml @@ -1,7 +1,10 @@ +@using OneForMe.Services +@inject LocalizationService Localizer + @model OneForMe.Models.Order @{ - ViewData["Title"] = "Join Order"; + ViewData["Title"] = Localizer["JoinOrder"]; }
@@ -10,14 +13,14 @@

@Model.CreatorName

-

Order Code: @Model.OrderCode

-

Created by: @Model.CreatorName

+

@Localizer["Code"]: @Model.OrderCode

+

@Localizer["CreatedBy"]: @Model.CreatorName

-
Available Items
+
@Localizer["MenuItems"]
@if (Model.MenuItems.Any()) @@ -26,19 +29,19 @@
- - + +
- - + +
- +
- Total: $0.00 + @Localizer["Total"]: $0.00
- - Back to Dashboard + + @Localizer["BackToDashboard"] } else { -

No items available for this order

+

@Localizer["NoItemsAvailable"]

}
@@ -70,7 +73,7 @@
-
Current Orders (@Model.OrderItems.Count)
+
@Localizer["CurrentOrders"] (@Model.OrderItems.Count)
@if (Model.OrderItems.Any()) @@ -78,10 +81,10 @@
ParticipantItemQtyTotal@Localizer.Get("Participant")@Localizer.Get("Item")@Localizer.Get("Qty")@Localizer.Get("Total")
- - - - + + + + @@ -91,7 +94,7 @@ - + } @@ -103,8 +106,8 @@
NameItemQtyTotal@Localizer["Participant"]@Localizer["Item"]@Localizer["Qty"]@Localizer["Total"]
@orderItem.ParticipantName @orderItem.MenuItem?.Name @orderItem.Quantity$@(orderItem.MenuItem?.Price * orderItem.Quantity ?? 0).ToString("F2")$@((orderItem.MenuItem?.Price * orderItem.Quantity ?? 0).ToString("F2"))
- - + + @@ -121,14 +124,14 @@ } else { -

No one has ordered yet

+

@Localizer["NoOrdersYet"]

}
-
Order Total
+
@Localizer["OrderTotal"]

$@Model.OrderItems.Sum(oi => oi.MenuItem.Price * oi.Quantity).ToString("F2")

PersonOwes@Localizer["Person"]@Localizer["Owes"]