diff --git a/Blazor.csproj b/Blazor.csproj
index 1801469..fd8c416 100644
--- a/Blazor.csproj
+++ b/Blazor.csproj
@@ -6,6 +6,10 @@
enable
+
+
+
+
@@ -18,6 +22,10 @@
+
+
+
+
Always
diff --git a/Component/Card.razor b/Component/Card.razor
new file mode 100644
index 0000000..422077c
--- /dev/null
+++ b/Component/Card.razor
@@ -0,0 +1,6 @@
+@typeparam TItem
+
+ @CardHeader(Item)
+ @CardBody(Item)
+ @CardFooter
+
\ No newline at end of file
diff --git a/Component/Card.razor.cs b/Component/Card.razor.cs
new file mode 100644
index 0000000..86dae2d
--- /dev/null
+++ b/Component/Card.razor.cs
@@ -0,0 +1,16 @@
+using Microsoft.AspNetCore.Components;
+
+public partial class Card
+{
+ [Parameter]
+ public RenderFragment CardBody { get; set; }
+
+ [Parameter]
+ public RenderFragment CardFooter { get; set; }
+
+ [Parameter]
+ public RenderFragment CardHeader { get; set; }
+
+ [Parameter]
+ public TItem Item { get; set; }
+}
\ No newline at end of file
diff --git a/Component/CraftingAction.cs b/Component/CraftingAction.cs
new file mode 100644
index 0000000..f96925a
--- /dev/null
+++ b/Component/CraftingAction.cs
@@ -0,0 +1,11 @@
+using Blazor.Models;
+
+namespace Blazor.Component
+{
+ public class CraftingAction
+ {
+ public string Action { get; set; }
+ public int Index { get; set; }
+ public Item Item { get; set; }
+ }
+}
diff --git a/Component/CraftingItem.razor b/Component/CraftingItem.razor
new file mode 100644
index 0000000..d43a742
--- /dev/null
+++ b/Component/CraftingItem.razor
@@ -0,0 +1,15 @@
+@using Models;
+
+
+
+ @if (Item != null)
+ {
+ @Item.DisplayName
+ }
+
\ No newline at end of file
diff --git a/Component/CraftingItem.razor.cs b/Component/CraftingItem.razor.cs
new file mode 100644
index 0000000..29a3a61
--- /dev/null
+++ b/Component/CraftingItem.razor.cs
@@ -0,0 +1,64 @@
+using Blazor.Models;
+using Blazorise;
+using Microsoft.AspNetCore.Components;
+
+namespace Blazor.Component
+{
+ public partial class CraftingItem
+ {
+ [Parameter]
+ public int Index { get; set; }
+
+ [Parameter]
+ public Item Item { get; set; }
+
+ [Parameter]
+ public bool NoDrop { get; set; }
+
+ [CascadingParameter]
+ public Crafting Parent { get; set; }
+
+ internal void OnDragEnter()
+ {
+ if (NoDrop)
+ {
+ return;
+ }
+
+ Parent.Actions.Add(new CraftingAction { Action = "Drag Enter", Item = this.Item, Index = this.Index });
+ }
+
+ internal void OnDragLeave()
+ {
+ if (NoDrop)
+ {
+ return;
+ }
+
+ Parent.Actions.Add(new CraftingAction { Action = "Drag Leave", Item = this.Item, Index = this.Index });
+ }
+
+ internal void OnDrop()
+ {
+ if (NoDrop)
+ {
+ return;
+ }
+
+ this.Item = Parent.CurrentDragItem;
+ Parent.RecipeItems[this.Index] = this.Item;
+
+ Parent.Actions.Add(new CraftingAction { Action = "Drop", Item = this.Item, Index = this.Index });
+
+ // Check recipe
+ Parent.CheckRecipe();
+ }
+
+ private void OnDragStart()
+ {
+ Parent.CurrentDragItem = this.Item;
+
+ Parent.Actions.Add(new CraftingAction { Action = "Drag Start", Item = this.Item, Index = this.Index });
+ }
+ }
+}
diff --git a/Component/CraftingRecipe.cs b/Component/CraftingRecipe.cs
new file mode 100644
index 0000000..1bd185e
--- /dev/null
+++ b/Component/CraftingRecipe.cs
@@ -0,0 +1,10 @@
+using Blazor.Models;
+
+namespace Blazor.Component
+{
+ public class CraftingRecipe
+ {
+ public Item Give { get; set; }
+ public List> Have { get; set; }
+ }
+}
diff --git a/Controller/CultureController.cs b/Controller/CultureController.cs
new file mode 100644
index 0000000..8075cd6
--- /dev/null
+++ b/Controller/CultureController.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Localization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blazor.controller
+{
+ [Route("[controller]/[action]")]
+ public class CultureController : Controller
+ {
+ ///
+ /// Sets the culture.
+ ///
+ /// The culture.
+ /// The redirect URI.
+ ///
+ /// The action result.
+ ///
+ public IActionResult SetCulture(string culture, string redirectUri)
+ {
+ if (culture != null)
+ {
+ // Define a cookie with the selected culture
+ this.HttpContext.Response.Cookies.Append(
+ CookieRequestCultureProvider.DefaultCookieName,
+ CookieRequestCultureProvider.MakeCookieValue(
+ new RequestCulture(culture)));
+ }
+
+ return this.LocalRedirect(redirectUri);
+ }
+ }
+}
diff --git a/Models/Cake.cs b/Models/Cake.cs
new file mode 100644
index 0000000..a8d6b37
--- /dev/null
+++ b/Models/Cake.cs
@@ -0,0 +1,9 @@
+namespace Blazor.Models
+{
+ public class Cake
+ {
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public decimal Cost { get; set; }
+ }
+}
diff --git a/Pages/Edit.razor b/Pages/Edit.razor
index 74d3978..fca6827 100644
--- a/Pages/Edit.razor
+++ b/Pages/Edit.razor
@@ -1,4 +1,6 @@
@page "/edit/{Id:int}"
+@using System.Globalization
+@using Models;
Edit
@@ -78,5 +80,9 @@
+
+ CurrentCulture: @CultureInfo.CurrentCulture
+
+
\ No newline at end of file
diff --git a/Pages/Edit.razor.cs b/Pages/Edit.razor.cs
index b01bea7..6d6034f 100644
--- a/Pages/Edit.razor.cs
+++ b/Pages/Edit.razor.cs
@@ -1,118 +1,121 @@
-using Blazor.Models;
-using Blazor.Services;
+using Blazor.Services;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components;
using Blazor.Factories;
+using Blazor.Models;
-public partial class Edit
+namespace Blazor.Edit
{
- [Parameter]
- public int Id { get; set; }
-
- ///
- /// The default enchant categories.
- ///
- private List enchantCategories = new List() { "armor", "armor_head", "armor_chest", "weapon", "digger", "breakable", "vanishable" };
-
- ///
- /// The current item model
- ///
- private ItemModel itemModel = new()
+ public partial class Edit
{
- EnchantCategories = new List(),
- RepairWith = new List()
- };
-
- ///
- /// The default repair with.
- ///
- private List repairWith = new List() { "oak_planks", "spruce_planks", "birch_planks", "jungle_planks", "acacia_planks", "dark_oak_planks", "crimson_planks", "warped_planks" };
-
- [Inject]
- public IDataService DataService { get; set; }
+ [Parameter]
+ public int Id { get; set; }
+
+ ///
+ /// The default enchant categories.
+ ///
+ private List enchantCategories = new List() { "armor", "armor_head", "armor_chest", "weapon", "digger", "breakable", "vanishable" };
+
+ ///
+ /// The current item model
+ ///
+ private ItemModel itemModel = new()
+ {
+ EnchantCategories = new List(),
+ RepairWith = new List()
+ };
- [Inject]
- public NavigationManager NavigationManager { get; set; }
+ ///
+ /// The default repair with.
+ ///
+ private List repairWith = new List() { "oak_planks", "spruce_planks", "birch_planks", "jungle_planks", "acacia_planks", "dark_oak_planks", "crimson_planks", "warped_planks" };
- [Inject]
- public IWebHostEnvironment WebHostEnvironment { get; set; }
+ [Inject]
+ public IDataService DataService { get; set; }
- protected override async Task OnInitializedAsync()
- {
- var item = await DataService.GetById(Id);
+ [Inject]
+ public NavigationManager NavigationManager { get; set; }
- var fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/default.png");
+ [Inject]
+ public IWebHostEnvironment WebHostEnvironment { get; set; }
- if (File.Exists($"{WebHostEnvironment.WebRootPath}/images/{itemModel.Name}.png"))
+ protected async Task OnInitializedAsync()
{
- fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/{item.Name}.png");
- }
+ var item = await DataService.GetById(Id);
- // Set the model with the item
- itemModel = new ItemModel
- {
- Id = item.Id,
- DisplayName = item.DisplayName,
- Name = item.Name,
- RepairWith = item.RepairWith,
- EnchantCategories = item.EnchantCategories,
- MaxDurability = item.MaxDurability,
- StackSize = item.StackSize,
- ImageContent = fileContent
- };
- itemModel = ItemFactory.ToModel(item, fileContent);
- }
+ var fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/default.png");
- private async void HandleValidSubmit()
- {
- await DataService.Update(Id, itemModel);
-
- NavigationManager.NavigateTo("list");
- }
+ if (File.Exists($"{WebHostEnvironment.WebRootPath}/images/{itemModel.Name}.png"))
+ {
+ fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/{item.Name}.png");
+ }
- private async Task LoadImage(InputFileChangeEventArgs e)
- {
- // Set the content of the image to the model
- using (var memoryStream = new MemoryStream())
- {
- await e.File.OpenReadStream().CopyToAsync(memoryStream);
- itemModel.ImageContent = memoryStream.ToArray();
+ // Set the model with the item
+ itemModel = new ItemModel
+ {
+ Id = item.Id,
+ DisplayName = item.DisplayName,
+ Name = item.Name,
+ RepairWith = item.RepairWith,
+ EnchantCategories = item.EnchantCategories,
+ MaxDurability = item.MaxDurability,
+ StackSize = item.StackSize,
+ ImageContent = fileContent
+ };
+ itemModel = ItemFactory.ToModel(item, fileContent);
}
- }
- private void OnEnchantCategoriesChange(string item, object checkedValue)
- {
- if ((bool)checkedValue)
+ private async void HandleValidSubmit()
{
- if (!itemModel.EnchantCategories.Contains(item))
- {
- itemModel.EnchantCategories.Add(item);
- }
+ await DataService.Update(Id, itemModel);
- return;
+ NavigationManager.NavigateTo("list");
}
- if (itemModel.EnchantCategories.Contains(item))
+ private async Task LoadImage(InputFileChangeEventArgs e)
{
- itemModel.EnchantCategories.Remove(item);
+ // Set the content of the image to the model
+ using (var memoryStream = new MemoryStream())
+ {
+ await e.File.OpenReadStream().CopyToAsync(memoryStream);
+ itemModel.ImageContent = memoryStream.ToArray();
+ }
}
- }
- private void OnRepairWithChange(string item, object checkedValue)
- {
- if ((bool)checkedValue)
+ private void OnEnchantCategoriesChange(string item, object checkedValue)
{
- if (!itemModel.RepairWith.Contains(item))
+ if ((bool)checkedValue)
{
- itemModel.RepairWith.Add(item);
+ if (!itemModel.EnchantCategories.Contains(item))
+ {
+ itemModel.EnchantCategories.Add(item);
+ }
+
+ return;
}
- return;
+ if (itemModel.EnchantCategories.Contains(item))
+ {
+ itemModel.EnchantCategories.Remove(item);
+ }
}
- if (itemModel.RepairWith.Contains(item))
+ private void OnRepairWithChange(string item, object checkedValue)
{
- itemModel.RepairWith.Remove(item);
+ if ((bool)checkedValue)
+ {
+ if (!itemModel.RepairWith.Contains(item))
+ {
+ itemModel.RepairWith.Add(item);
+ }
+
+ return;
+ }
+
+ if (itemModel.RepairWith.Contains(item))
+ {
+ itemModel.RepairWith.Remove(item);
+ }
}
}
}
\ No newline at end of file
diff --git a/Pages/Index.razor b/Pages/Index.razor
index 6085c4a..fd7bfa4 100644
--- a/Pages/Index.razor
+++ b/Pages/Index.razor
@@ -1,4 +1,6 @@
@page "/"
+@using System.Globalization
+@using Blazor.Models;
Index
@@ -6,4 +8,26 @@
Welcome to your new app.
+
+ CurrentCulture: @CultureInfo.CurrentCulture
+
+
+
+
+
+
+
+
@context.Name
+
$ @context.Cost
+
+
+
+
+
+
+
diff --git a/Pages/Index.razor.cs b/Pages/Index.razor.cs
new file mode 100644
index 0000000..db6aa01
--- /dev/null
+++ b/Pages/Index.razor.cs
@@ -0,0 +1,14 @@
+using Blazor.Models;
+
+namespace Blazor.Pages
+{
+ public partial class Index
+ {
+ private Cake CakeItem = new Cake
+ {
+ Id = 1,
+ Name = "Black Forest",
+ Cost = 50
+ };
+ }
+}
diff --git a/Pages/List.razor b/Pages/List.razor
index a67e444..6805347 100644
--- a/Pages/List.razor
+++ b/Pages/List.razor
@@ -1,7 +1,7 @@
@page "/list"
@using Models;
-List
+@Localizer["Title"]
diff --git a/Pages/List.razor.cs b/Pages/List.razor.cs
index 2c14712..cf4d2d0 100644
--- a/Pages/List.razor.cs
+++ b/Pages/List.razor.cs
@@ -5,6 +5,7 @@ using Blazored.Modal;
using Blazored.Modal.Services;
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
+using Microsoft.Extensions.Localization;
namespace Blazor.Pages{
public partial class List
@@ -25,6 +26,9 @@ namespace Blazor.Pages{
[CascadingParameter]
public IModalService Modal { get; set; }
+ [Inject]
+ public IStringLocalizer Localizer { get; set; }
+
private async void OnDelete(int id)
{
var parameters = new ModalParameters();
diff --git a/Program.cs b/Program.cs
index 77ed601..16d79f7 100644
--- a/Program.cs
+++ b/Program.cs
@@ -7,6 +7,9 @@ using Blazorise.Icons.FontAwesome;
using Blazored.Modal;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
+using Microsoft.AspNetCore.Localization;
+using System.Globalization;
+using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
@@ -24,6 +27,22 @@ builder.Services
builder.Services.AddBlazoredLocalStorage();
builder.Services.AddScoped();
+// Add the controller of the app
+builder.Services.AddControllers();
+
+// Add the localization to the app and specify the resources path
+builder.Services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
+
+// Configure the localtization
+builder.Services.Configure(options =>
+{
+ // Set the default culture of the web site
+ options.DefaultRequestCulture = new RequestCulture(new CultureInfo("en-US"));
+
+ // Declare the supported culture
+ options.SupportedCultures = new List { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
+ options.SupportedUICultures = new List { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
+});
var app = builder.Build();
@@ -41,6 +60,22 @@ app.UseStaticFiles();
app.UseRouting();
+// Get the current localization options
+var options = ((IApplicationBuilder)app).ApplicationServices.GetService>();
+
+if (options?.Value != null)
+{
+ // use the default localization
+ app.UseRequestLocalization(options.Value);
+}
+
+// Add the controller to the endpoint
+app.UseEndpoints(endpoints =>
+{
+ endpoints.MapControllers();
+});
+
+
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
builder.Services.AddScoped();
diff --git a/Resources/Pages.List.fr-FR.resx b/Resources/Pages.List.fr-FR.resx
new file mode 100644
index 0000000..50bb302
--- /dev/null
+++ b/Resources/Pages.List.fr-FR.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Liste des éléments
+
+
\ No newline at end of file
diff --git a/Resources/Pages.List.resx b/Resources/Pages.List.resx
new file mode 100644
index 0000000..ae67689
--- /dev/null
+++ b/Resources/Pages.List.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Items List
+
+
\ No newline at end of file
diff --git a/Shared/CultureSelector.razor b/Shared/CultureSelector.razor
new file mode 100644
index 0000000..6d7f012
--- /dev/null
+++ b/Shared/CultureSelector.razor
@@ -0,0 +1,43 @@
+@using System.Globalization
+@inject NavigationManager NavigationManager
+
+
+
+
+
+@code
+{
+ private CultureInfo[] supportedCultures = new[]
+ {
+ new CultureInfo("en-US"),
+ new CultureInfo("fr-FR")
+ };
+
+ private CultureInfo Culture
+ {
+ get => CultureInfo.CurrentCulture;
+ set
+ {
+ if (CultureInfo.CurrentUICulture == value)
+ {
+ return;
+ }
+
+ var culture = value.Name.ToLower(CultureInfo.InvariantCulture);
+
+ var uri = new Uri(this.NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
+ var query = $"?culture={Uri.EscapeDataString(culture)}&" + $"redirectUri={Uri.EscapeDataString(uri)}";
+
+ // Redirect the user to the culture controller to set the cookie
+ this.NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Shared/MainLayout.razor b/Shared/MainLayout.razor
index 39af19b..04ab34f 100644
--- a/Shared/MainLayout.razor
+++ b/Shared/MainLayout.razor
@@ -10,6 +10,9 @@