nettoyage des warning, ajout de localization #22

Merged
mcmuzzle merged 1 commits from 18_miseEnPlacePageCreationMatch into main 2024-09-10 14:50:27 +00:00
21 changed files with 376 additions and 122 deletions

View File

@@ -6,6 +6,7 @@ root = true
dotnet_diagnostic.IDE1006.severity = warning dotnet_diagnostic.IDE1006.severity = warning
dotnet_diagnostic.IDE0005.severity = error dotnet_diagnostic.IDE0005.severity = error
dotnet_diagnostic.CA5394.severity = none dotnet_diagnostic.CA5394.severity = none
dotnet_diagnostic.CA1848.severity = none #optimisatio logger pas nécessaire
# Exclude generated code # Exclude generated code
[src/**/Migrations/*.cs] [src/**/Migrations/*.cs]

View File

@@ -45,7 +45,7 @@ internal static class IdentityComponentsEndpointRouteBuilderExtensions
SignInManager<ApplicationUser> signInManager, SignInManager<ApplicationUser> signInManager,
[FromForm] string returnUrl) => [FromForm] string returnUrl) =>
{ {
await signInManager.SignOutAsync(); await signInManager.SignOutAsync().ConfigureAwait(true);
return TypedResults.LocalRedirect($"~/{returnUrl}"); return TypedResults.LocalRedirect($"~/{returnUrl}");
}); });
@@ -57,7 +57,7 @@ internal static class IdentityComponentsEndpointRouteBuilderExtensions
[FromForm] string provider) => [FromForm] string provider) =>
{ {
// Clear the existing external cookie to ensure a clean login process // Clear the existing external cookie to ensure a clean login process
await context.SignOutAsync(IdentityConstants.ExternalScheme); await context.SignOutAsync(IdentityConstants.ExternalScheme).ConfigureAwait(false);
var redirectUrl = UriHelper.BuildRelative( var redirectUrl = UriHelper.BuildRelative(
context.Request.PathBase, context.Request.PathBase,
@@ -76,13 +76,13 @@ internal static class IdentityComponentsEndpointRouteBuilderExtensions
[FromServices] UserManager<ApplicationUser> userManager, [FromServices] UserManager<ApplicationUser> userManager,
[FromServices] AuthenticationStateProvider authenticationStateProvider) => [FromServices] AuthenticationStateProvider authenticationStateProvider) =>
{ {
var user = await userManager.GetUserAsync(context.User); var user = await userManager.GetUserAsync(context.User).ConfigureAwait(false);
if (user is null) if (user is null)
{ {
return Results.NotFound($"Unable to load user with ID '{userManager.GetUserId(context.User)}'."); return Results.NotFound($"Unable to load user with ID '{userManager.GetUserId(context.User)}'.");
} }
var userId = await userManager.GetUserIdAsync(user); var userId = await userManager.GetUserIdAsync(user).ConfigureAwait(false);
downloadLogger.LogInformation("User with ID '{UserId}' asked for their personal data.", userId); downloadLogger.LogInformation("User with ID '{UserId}' asked for their personal data.", userId);
// Only include personal data for download // Only include personal data for download
@@ -94,13 +94,13 @@ internal static class IdentityComponentsEndpointRouteBuilderExtensions
personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null"); personalData.Add(p.Name, p.GetValue(user)?.ToString() ?? "null");
} }
var logins = await userManager.GetLoginsAsync(user); var logins = await userManager.GetLoginsAsync(user).ConfigureAwait(false);
foreach (var l in logins) foreach (var l in logins)
{ {
personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey); personalData.Add($"{l.LoginProvider} external login provider key", l.ProviderKey);
} }
personalData.Add("Authenticator Key", (await userManager.GetAuthenticatorKeyAsync(user))!); personalData.Add("Authenticator Key", (await userManager.GetAuthenticatorKeyAsync(user).ConfigureAwait(false))!);
var fileBytes = JsonSerializer.SerializeToUtf8Bytes(personalData); var fileBytes = JsonSerializer.SerializeToUtf8Bytes(personalData);
context.Response.Headers.TryAdd("Content-Disposition", "attachment; filename=PersonalData.json"); context.Response.Headers.TryAdd("Content-Disposition", "attachment; filename=PersonalData.json");

View File

@@ -4,10 +4,12 @@ using LudikZoneBlazor.Data;
namespace LudikZoneBlazor.Components.Account; namespace LudikZoneBlazor.Components.Account;
// Remove the "else if (EmailSender is IdentityNoOpEmailSender)" block from RegisterConfirmation.razor after updating with a real implementation. #pragma warning disable CA1812 // Elle est instanciée en Injection de dependance
/// <summary> Remove the "else if (EmailSender is IdentityNoOpEmailSender)" block from RegisterConfirmation.razor after updating with a real implementation. </summary>
internal sealed class IdentityNoOpEmailSender : IEmailSender<ApplicationUser> internal sealed class IdentityNoOpEmailSender : IEmailSender<ApplicationUser>
{ {
private readonly IEmailSender emailSender = new NoOpEmailSender(); private readonly NoOpEmailSender emailSender = new NoOpEmailSender();
public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink) => public Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink) =>
emailSender.SendEmailAsync(email, "Confirm your email", $"Please confirm your account by <a href='{confirmationLink}'>clicking here</a>."); emailSender.SendEmailAsync(email, "Confirm your email", $"Please confirm your account by <a href='{confirmationLink}'>clicking here</a>.");
@@ -18,3 +20,5 @@ internal sealed class IdentityNoOpEmailSender : IEmailSender<ApplicationUser>
public Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode) => public Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode) =>
emailSender.SendEmailAsync(email, "Reset your password", $"Please reset your password using the following code: {resetCode}"); emailSender.SendEmailAsync(email, "Reset your password", $"Please reset your password using the following code: {resetCode}");
} }
#pragma warning restore CA1812

View File

@@ -3,6 +3,8 @@ using Microsoft.AspNetCore.Components;
namespace LudikZoneBlazor.Components.Account; namespace LudikZoneBlazor.Components.Account;
#pragma warning disable CA1812 // Elle est instanciée en Injection de dependance
internal sealed class IdentityRedirectManager(NavigationManager navigationManager) internal sealed class IdentityRedirectManager(NavigationManager navigationManager)
{ {
public const string StatusCookieName = "Identity.StatusMessage"; public const string StatusCookieName = "Identity.StatusMessage";
@@ -56,3 +58,5 @@ internal sealed class IdentityRedirectManager(NavigationManager navigationManage
public void RedirectToCurrentPageWithStatus(string message, HttpContext context) public void RedirectToCurrentPageWithStatus(string message, HttpContext context)
=> RedirectToWithStatus(CurrentPath, message, context); => RedirectToWithStatus(CurrentPath, message, context);
} }
#pragma warning restore CA1812

View File

@@ -7,6 +7,8 @@ using LudikZoneBlazor.Data;
namespace LudikZoneBlazor.Components.Account; namespace LudikZoneBlazor.Components.Account;
#pragma warning disable CA1812 // Elle est instanciée en Injection de dependance
// This is a server-side AuthenticationStateProvider that revalidates the security stamp for the connected user // This is a server-side AuthenticationStateProvider that revalidates the security stamp for the connected user
// every 30 minutes an interactive circuit is connected. // every 30 minutes an interactive circuit is connected.
internal sealed class IdentityRevalidatingAuthenticationStateProvider( internal sealed class IdentityRevalidatingAuthenticationStateProvider(
@@ -21,14 +23,14 @@ internal sealed class IdentityRevalidatingAuthenticationStateProvider(
AuthenticationState authenticationState, CancellationToken cancellationToken) AuthenticationState authenticationState, CancellationToken cancellationToken)
{ {
// Get the user manager from a new scope to ensure it fetches fresh data // Get the user manager from a new scope to ensure it fetches fresh data
await using var scope = scopeFactory.CreateAsyncScope(); using AsyncServiceScope scope = scopeFactory.CreateAsyncScope();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>(); var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
return await ValidateSecurityStampAsync(userManager, authenticationState.User); return await ValidateSecurityStampAsync(userManager, authenticationState.User).ConfigureAwait(false);
} }
private async Task<bool> ValidateSecurityStampAsync(UserManager<ApplicationUser> userManager, ClaimsPrincipal principal) private async Task<bool> ValidateSecurityStampAsync(UserManager<ApplicationUser> userManager, ClaimsPrincipal principal)
{ {
var user = await userManager.GetUserAsync(principal); var user = await userManager.GetUserAsync(principal).ConfigureAwait(false);
if (user is null) if (user is null)
{ {
return false; return false;
@@ -40,8 +42,10 @@ internal sealed class IdentityRevalidatingAuthenticationStateProvider(
else else
{ {
var principalStamp = principal.FindFirstValue(options.Value.ClaimsIdentity.SecurityStampClaimType); var principalStamp = principal.FindFirstValue(options.Value.ClaimsIdentity.SecurityStampClaimType);
var userStamp = await userManager.GetSecurityStampAsync(user); var userStamp = await userManager.GetSecurityStampAsync(user).ConfigureAwait(false);
return principalStamp == userStamp; return principalStamp == userStamp;
} }
} }
} }
#pragma warning restore CA1812

View File

@@ -3,11 +3,13 @@ using LudikZoneBlazor.Data;
namespace LudikZoneBlazor.Components.Account; namespace LudikZoneBlazor.Components.Account;
#pragma warning disable CA1812 // Elle est instanciée en Injection de dependance
internal sealed class IdentityUserAccessor(UserManager<ApplicationUser> userManager, IdentityRedirectManager redirectManager) internal sealed class IdentityUserAccessor(UserManager<ApplicationUser> userManager, IdentityRedirectManager redirectManager)
{ {
public async Task<ApplicationUser> GetRequiredUserAsync(HttpContext context) public async Task<ApplicationUser> GetRequiredUserAsync(HttpContext context)
{ {
var user = await userManager.GetUserAsync(context.User); var user = await userManager.GetUserAsync(context.User).ConfigureAwait(false);
if (user is null) if (user is null)
{ {
@@ -17,3 +19,5 @@ internal sealed class IdentityUserAccessor(UserManager<ApplicationUser> userMana
return user; return user;
} }
} }
#pragma warning restore CA1812

View File

@@ -4,12 +4,11 @@
<MudNavMenu> <MudNavMenu>
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink> <MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
<MudNavLink Href="counter" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Add">Counter</MudNavLink> <MudNavLink Href="Games" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.VideogameAsset">Games</MudNavLink>
<MudNavLink Href="weather" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.List">Weather</MudNavLink>
<MudNavLink Href="auth" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Lock">Auth Required</MudNavLink>
<AuthorizeView> <AuthorizeView>
<Authorized> <Authorized>
<MudNavLink Href="Account/Manage" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Person">@context.User.Identity?.Name</MudNavLink> <MudNavLink Href="Account/Manage" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Person">
@context.User.Identity?.Name</MudNavLink>
<form action="Account/Logout" method="post"> <form action="Account/Logout" method="post">
<AntiforgeryToken /> <AntiforgeryToken />
<input type="hidden" name="ReturnUrl" value="@currentUrl" /> <input type="hidden" name="ReturnUrl" value="@currentUrl" />
@@ -19,8 +18,10 @@
</form> </form>
</Authorized> </Authorized>
<NotAuthorized> <NotAuthorized>
<MudNavLink Href="Account/Register" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Person">Register</MudNavLink> <MudNavLink Href="Account/Register" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Person">
<MudNavLink Href="Account/Login" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Password">Login</MudNavLink> Register</MudNavLink>
<MudNavLink Href="Account/Login" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Password">Login
</MudNavLink>
</NotAuthorized> </NotAuthorized>
</AuthorizeView> </AuthorizeView>
</MudNavMenu> </MudNavMenu>
@@ -46,5 +47,3 @@
NavigationManager.LocationChanged -= OnLocationChanged; NavigationManager.LocationChanged -= OnLocationChanged;
} }
} }

View File

@@ -1,14 +0,0 @@
@page "/auth"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>Auth</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true">You are authenticated!</MudText>
<AuthorizeView>
<MudText Class="mb-4">Hello @context.User.Identity?.Name!</MudText>
</AuthorizeView>

View File

@@ -1,18 +0,0 @@
@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,28 @@
@page "/games"
@using Microsoft.AspNetCore.Authorization
@using LudikZoneBlazor.Data.Model
@attribute [Authorize]
@inject IStringLocalizer<Games> localizer
<PageTitle>@localizer["Games"]</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true">@localizer["Game list"]</MudText>
<AuthorizeView>
@foreach (var g in GetGames())
{
}
</AuthorizeView>
@code {
private List<Game> GetGames()
{
return new List<Game>();
}
}

View File

@@ -39,11 +39,16 @@
<br /> <br />
<MudText Typo="Typo.h6" GutterBottom="true">Prerendering</MudText> <MudText Typo="Typo.h6" GutterBottom="true">Prerendering</MudText>
<MudText Typo="Typo.body2" GutterBottom="true"> <MudText Typo="Typo.body2" GutterBottom="true">
If you're exploring the features of .NET 8 Blazor,<br /> you might be pleasantly surprised to learn that each page is prerendered on the server,<br /> regardless of the selected render mode.<br /><br /> If you're exploring the features of .NET 8 Blazor,<br /> you might be pleasantly surprised to learn that each page
This means that you'll need to inject all necessary services on the server,<br /> even when opting for the wasm (WebAssembly) render mode.<br /><br /> is prerendered on the server,<br /> regardless of the selected render mode.<br /><br />
This prerendering functionality is crucial to ensuring that WebAssembly mode feels fast and responsive,<br /> especially when it comes to initial page load times.<br /><br /> This means that you'll need to inject all necessary services on the server,<br /> even when opting for the wasm
For more information on how to detect prerendering and leverage the RenderContext, you can refer to the following link: (WebAssembly) render mode.<br /><br />
<MudLink Href="https://github.com/dotnet/aspnetcore/issues/51468#issuecomment-1783568121" Target="_blank" Typo="Typo.body2" Color="Color.Primary"> This prerendering functionality is crucial to ensuring that WebAssembly mode feels fast and responsive,<br />
especially when it comes to initial page load times.<br /><br />
For more information on how to detect prerendering and leverage the RenderContext, you can refer to the following
link:
<MudLink Href="https://github.com/dotnet/aspnetcore/issues/51468#issuecomment-1783568121" Target="_blank"
Typo="Typo.body2" Color="Color.Primary">
More details More details
</MudLink> </MudLink>
</MudText> </MudText>
@@ -52,7 +57,8 @@
<MudText Typo="Typo.h6" GutterBottom="true">InteractiveAuto</MudText> <MudText Typo="Typo.h6" GutterBottom="true">InteractiveAuto</MudText>
<MudText Typo="Typo.body2"> <MudText Typo="Typo.body2">
A discussion on how to achieve this can be found here: A discussion on how to achieve this can be found here:
<MudLink Href="https://github.com/dotnet/aspnetcore/issues/51468#issue-1950424116" Target="_blank" Typo="Typo.body2" Color="Color.Primary"> <MudLink Href="https://github.com/dotnet/aspnetcore/issues/51468#issue-1950424116" Target="_blank" Typo="Typo.body2"
Color="Color.Primary">
More details More details
</MudLink> </MudLink>
</MudText> </MudText>

View File

@@ -1,60 +0,0 @@
@page "/weather"
<PageTitle>Weather</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true">Weather forecast</MudText>
<MudText Typo="Typo.body1" Class="mb-8">This component demonstrates fetching data from the server.</MudText>
@if (forecasts == null)
{
<MudProgressCircular Color="Color.Default" Indeterminate="true" />
}
else
{
<MudTable Items="forecasts" Hover="true" SortLabel="Sort By" Elevation="0" AllowUnsorted="false">
<HeaderContent>
<MudTh><MudTableSortLabel InitialDirection="SortDirection.Ascending" SortBy="new Func<WeatherForecast, object>(x=>x.Date)">Date</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<WeatherForecast, object>(x=>x.TemperatureC)">Temp. (C)</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<WeatherForecast, object>(x=>x.TemperatureF)">Temp. (F)</MudTableSortLabel></MudTh>
<MudTh><MudTableSortLabel SortBy="new Func<WeatherForecast, object>(x=>x.Summary!)">Summary</MudTableSortLabel></MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Date">@context.Date</MudTd>
<MudTd DataLabel="Temp. (C)">@context.TemperatureC</MudTd>
<MudTd DataLabel="Temp. (F)">@context.TemperatureF</MudTd>
<MudTd DataLabel="Summary">@context.Summary</MudTd>
</RowTemplate>
<PagerContent>
<MudTablePager PageSizeOptions="new int[]{50, 100}" />
</PagerContent>
</MudTable>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
// Simulate asynchronous loading to demonstrate a loading indicator
await Task.Delay(500);
var startDate = DateOnly.FromDateTime(DateTime.Now);
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
}
private class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

View File

@@ -12,3 +12,4 @@
@using MudBlazor.Services @using MudBlazor.Services
@using LudikZoneBlazor @using LudikZoneBlazor
@using LudikZoneBlazor.Components @using LudikZoneBlazor.Components
@using Microsoft.Extensions.Localization

View File

@@ -1,8 +1,17 @@
using LudikZoneBlazor.Data.Model;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace LudikZoneBlazor.Data; namespace LudikZoneBlazor.Data;
/// <summary>
/// Le context BDD de l'application
/// </summary>
/// <param name="options"></param>
public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : IdentityDbContext<ApplicationUser>(options) public class ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : IdentityDbContext<ApplicationUser>(options)
{ {
/// <summary> Tout les jeux existant sur la plateforme </summary>
public virtual DbSet<Game> Games => Set<Game>();
} }

View File

@@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Identity;
namespace LudikZoneBlazor.Data; namespace LudikZoneBlazor.Data;
// Add profile data for application users by adding properties to the ApplicationUser class /// <summary> Add profile data for application users by adding properties to the ApplicationUser class </summary>
public class ApplicationUser : IdentityUser public class ApplicationUser : IdentityUser
{ {
} }

View File

@@ -0,0 +1,11 @@
namespace LudikZoneBlazor.Data.Model;
/// <summary>
/// Informations relative a un jeu précis
/// </summary>
public class Game
{
/// <summary> Identifiant unique d'un jeu </summary>
public int Id { get; init; }
}

View File

@@ -4,6 +4,11 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisMode>All</AnalysisMode>
<UserSecretsId>aspnet-LudikZoneBlazor-b18f2a2e-d082-4232-8521-6cacaa2a4ba2</UserSecretsId> <UserSecretsId>aspnet-LudikZoneBlazor-b18f2a2e-d082-4232-8521-6cacaa2a4ba2</UserSecretsId>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,5 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable #nullable disable

View File

@@ -49,6 +49,10 @@ builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.Requ
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>(); builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
// Begin I18N configuration
builder.Services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
// End I18N configuration
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@@ -74,6 +78,17 @@ app.MapRazorComponents<App>()
// Add additional endpoints required by the Identity /Account Razor components. // Add additional endpoints required by the Identity /Account Razor components.
app.MapAdditionalIdentityEndpoints(); app.MapAdditionalIdentityEndpoints();
// Begin I18N configuration
var supportedCultures = new[] { "fr", "en" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
// End I18N configuration
// Appliquer les migrations automatiquement lors du démarrage // Appliquer les migrations automatiquement lors du démarrage
using (var scope = app.Services.CreateScope()) using (var scope = app.Services.CreateScope())
{ {

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Games" xml:space="preserve">
<value>Games anglais 4</value>
<comment>comment game</comment>
</data>
<data name="Game list" xml:space="preserve">
<value>Game list</value>
<comment>title game list</comment>
</data>
</root>

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string"/>
<xsd:attribute name="type" type="xsd:string"/>
<xsd:attribute name="mimetype" type="xsd:string"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string"/>
<xsd:attribute name="name" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
<xsd:attribute ref="xml:space"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Games" xml:space="preserve">
<value>Games francais 4</value>
<comment>comment game</comment>
</data>
<data name="Game list" xml:space="preserve">
<value>Liste des jeux</value>
<comment>Titre de la liste des jeux</comment>
</data>
</root>