Skip to content

Commit c912f30

Browse files
committed
Merge branch 'feature/246' into develop
2 parents 2bfdb01 + dba5bf2 commit c912f30

File tree

12 files changed

+161
-53
lines changed

12 files changed

+161
-53
lines changed

.github/workflows/codeql-analysis.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939

4040
steps:
4141
- name: Checkout repository
42-
uses: actions/checkout@v2
42+
uses: actions/checkout@v4.1.1
4343

4444
# Initializes the CodeQL tools for scanning.
4545
- name: Initialize CodeQL
@@ -52,9 +52,9 @@ jobs:
5252
# queries: ./path/to/local/query, your-org/your-repo/queries@main
5353

5454
- name: Setup .NET
55-
uses: actions/setup-dotnet@v1
55+
uses: actions/setup-dotnet@v4
5656
with:
57-
dotnet-version: 7.0.x
57+
dotnet-version: 8.0.x
5858

5959
# Build
6060
- run: dotnet build src/Simplify.Web.sln -v minimal

.vscode/launch.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "coreclr",
77
"request": "launch",
88
"preLaunchTask": "Build Angular Example",
9-
"program": "${workspaceFolder}/src/SampleApps/SampleApp.Angular/bin/Debug/net7.0/SampleApp.Angular.dll",
9+
"program": "${workspaceFolder}/src/SampleApps/SampleApp.Angular/bin/Debug/net8.0/SampleApp.Angular.dll",
1010
"cwd": "${workspaceFolder}/src/SampleApps/SampleApp.Angular/",
1111
"internalConsoleOptions": "openOnSessionStart",
1212
"serverReadyAction": {
@@ -23,8 +23,8 @@
2323
"type": "coreclr",
2424
"request": "launch",
2525
"preLaunchTask": "Build Classic Example",
26-
"program": "${workspaceFolder}/src/SampleApps/SampleApp.Classic/bin/Debug/net7.0/SampleApp.Classic.dll",
27-
"cwd": "${workspaceFolder}/src/SampleApps/SampleApp.Classic/bin/Debug/net7.0/",
26+
"program": "${workspaceFolder}/src/SampleApps/SampleApp.Classic/bin/Debug/net8.0/SampleApp.Classic.dll",
27+
"cwd": "${workspaceFolder}/src/SampleApps/SampleApp.Classic/bin/Debug/net8.0/",
2828
"internalConsoleOptions": "openOnSessionStart",
2929
"serverReadyAction": {
3030
"action": "openExternally",

src/SampleApps/SampleApp.Angular/SampleApp.Angular.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22
<PropertyGroup>
3-
<TargetFramework>net7.0</TargetFramework>
3+
<TargetFramework>net8.0</TargetFramework>
44
<Nullable>enable</Nullable>
55
<ImplicitUsings>enable</ImplicitUsings>
66

src/SampleApps/SampleApp.Classic.Tests/SampleApp.Classic.Tests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>net7.0</TargetFramework>
3+
<TargetFramework>net8.0</TargetFramework>
44

55
<Authors>Alexander Krylkov</Authors>
66
<Product>Simplify</Product>

src/SampleApps/SampleApp.Classic/SampleApp.Classic.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk" InitialTargets="BeforeBuild">
22
<PropertyGroup>
3-
<TargetFramework>net7.0</TargetFramework>
3+
<TargetFramework>net8.0</TargetFramework>
44
<OutputType>Exe</OutputType>
55
<IsPackable>false</IsPackable>
66

src/Simplify.Web.RegistrationsTests/Simplify.Web.RegistrationsTests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>net7.0</TargetFramework>
3+
<TargetFramework>net8.0</TargetFramework>
44
<Nullable>enable</Nullable>
55
<WarningsAsErrors>nullable</WarningsAsErrors>
66

src/Simplify.Web.Tests/Modules/LanguageManagerTests.cs

+67-14
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ public void Initialize()
2323
{
2424
_settings = new Mock<ISimplifyWebSettings>();
2525
_context = new Mock<HttpContext>();
26+
_responseCookies = new Mock<IResponseCookies>();
2627

2728
_settings.SetupGet(x => x.DefaultLanguage).Returns("en");
28-
_responseCookies = new Mock<IResponseCookies>();
2929

3030
_context.SetupGet(x => x.Request.Cookies).Returns(Mock.Of<IRequestCookieCollection>());
3131
_context.SetupGet(x => x.Response.Cookies).Returns(_responseCookies.Object);
@@ -34,23 +34,29 @@ public void Initialize()
3434
}
3535

3636
[Test]
37-
public void Constructor_NoRequestCookieLanguage_DefaultLanguageSet()
37+
public void Constructor_NoRequestCookieLanguageAndCookieLanguageIsEnabled_DefaultLanguageSet()
3838
{
39+
// Arrange
40+
_settings.SetupGet(x => x.AcceptCookieLanguage).Returns(true);
41+
3942
// Assert
4043
Assert.AreEqual("en", _languageManager.Language);
4144
}
4245

4346
[Test]
44-
public void Constructor_HaveRequestCookie_CurrentLanguageSet()
47+
public void Constructor_HaveRequestCookieLanguageAndCookieLanguageIsEnabled_CurrentLanguageSet()
4548
{
4649
// Assign
4750

4851
var cookieCollection = new Mock<IRequestCookieCollection>();
52+
4953
cookieCollection.SetupGet(x => x[It.Is<string>(s => s == LanguageManager.CookieLanguageFieldName)]).Returns("ru");
50-
_context.SetupGet(x => x.Request.Cookies).Returns(cookieCollection.Object);
5154

55+
_settings.SetupGet(x => x.AcceptCookieLanguage).Returns(true);
5256
_settings.SetupGet(x => x.DefaultLanguage).Returns("en");
5357

58+
_context.SetupGet(x => x.Request.Cookies).Returns(cookieCollection.Object);
59+
5460
// Act
5561
_languageManager = new LanguageManager(_settings.Object, _context.Object);
5662

@@ -70,9 +76,10 @@ public void SetCookieLanguage_CorrectLanguage_CorrectCookieCreated()
7076
{
7177
// Assign
7278

73-
_settings.SetupGet(x => x.DefaultLanguage).Returns("en");
7479
_languageManager = new LanguageManager(_settings.Object, _context.Object);
7580

81+
_settings.SetupGet(x => x.DefaultLanguage).Returns("en");
82+
7683
_responseCookies.Setup(x => x.Append(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, value) =>
7784
{
7885
Assert.AreEqual("Set-Cookie", key);
@@ -84,13 +91,15 @@ public void SetCookieLanguage_CorrectLanguage_CorrectCookieCreated()
8491
}
8592

8693
[Test]
87-
public void Constructor_HaveBrowserLanguageAndSettingIsEnabledCase1_LanguageSetFromHeader()
94+
public void Constructor_HaveHeaderLanguageAndSettingIsEnabledCase1_LanguageSetFromHeader()
8895
{
8996
// Assign
9097

91-
_settings.SetupGet(x => x.AcceptBrowserLanguage).Returns(true);
9298
var header = new HeaderDictionary(new Dictionary<string, StringValues>());
99+
93100
header.Append("Accept-Language", "ru-RU");
101+
102+
_settings.SetupGet(x => x.AcceptHeaderLanguage).Returns(true);
94103
_context.SetupGet(x => x.Request.Headers).Returns(header);
95104

96105
// Act
@@ -101,13 +110,15 @@ public void Constructor_HaveBrowserLanguageAndSettingIsEnabledCase1_LanguageSetF
101110
}
102111

103112
[Test]
104-
public void Constructor_HaveBrowserLanguageAndSettingIsEnabledCase2_LanguageSetFromHeader()
113+
public void Constructor_HaveHeaderLanguageAndSettingIsEnabledCase2_LanguageSetFromHeader()
105114
{
106115
// Assign
107116

108-
_settings.SetupGet(x => x.AcceptBrowserLanguage).Returns(true);
109117
var header = new HeaderDictionary(new Dictionary<string, StringValues>());
118+
110119
header.Append("Accept-Language", "ru-RU;q=0.5");
120+
121+
_settings.SetupGet(x => x.AcceptHeaderLanguage).Returns(true);
111122
_context.SetupGet(x => x.Request.Headers).Returns(header);
112123

113124
// Act
@@ -118,33 +129,62 @@ public void Constructor_HaveBrowserLanguageAndSettingIsEnabledCase2_LanguageSetF
118129
}
119130

120131
[Test]
121-
public void Constructor_HaveBrowserLanguageAndCookieLanguage_LanguageSetFromCookie()
132+
public void Constructor_HaveHeaderLanguageAndCookieLanguageAndCookieLanguageIsEnabled_LanguageSetFromCookie()
122133
{
123134
// Assign
124135

125136
var cookieCollection = new Mock<IRequestCookieCollection>();
137+
var header = new HeaderDictionary(new Dictionary<string, StringValues>());
138+
139+
header.Append("Accept-Language", "ru-RU");
140+
126141
cookieCollection.SetupGet(x => x[It.Is<string>(s => s == LanguageManager.CookieLanguageFieldName)]).Returns("fr");
142+
143+
_settings.SetupGet(x => x.AcceptCookieLanguage).Returns(true);
144+
_settings.SetupGet(x => x.AcceptHeaderLanguage).Returns(true);
145+
127146
_context.SetupGet(x => x.Request.Cookies).Returns(cookieCollection.Object);
147+
_context.SetupGet(x => x.Request.Headers).Returns(header);
148+
149+
// Act
150+
_languageManager = new LanguageManager(_settings.Object, _context.Object);
128151

129-
_settings.SetupGet(x => x.AcceptBrowserLanguage).Returns(true);
152+
// Assert
153+
Assert.AreEqual("fr", _languageManager.Language);
154+
}
155+
156+
[Test]
157+
public void Constructor_HaveHeaderLanguageAndCookieLanguageAndCookieLanguageIsDisabled_LanguageSetFromHeader()
158+
{
159+
// Assign
160+
161+
var cookieCollection = new Mock<IRequestCookieCollection>();
130162
var header = new HeaderDictionary(new Dictionary<string, StringValues>());
163+
131164
header.Append("Accept-Language", "ru-RU");
165+
166+
cookieCollection.SetupGet(x => x[It.Is<string>(s => s == LanguageManager.CookieLanguageFieldName)]).Returns("fr");
167+
168+
_settings.SetupGet(x => x.AcceptHeaderLanguage).Returns(true);
169+
170+
_context.SetupGet(x => x.Request.Cookies).Returns(cookieCollection.Object);
132171
_context.SetupGet(x => x.Request.Headers).Returns(header);
133172

134173
// Act
135174
_languageManager = new LanguageManager(_settings.Object, _context.Object);
136175

137176
// Assert
138-
Assert.AreEqual("fr", _languageManager.Language);
177+
Assert.AreEqual("ru", _languageManager.Language);
139178
}
140179

141180
[Test]
142-
public void Constructor_NoBrowserLanguage_DefaultLanguageSet()
181+
public void Constructor_NoHeaderLanguage_DefaultLanguageSet()
143182
{
144183
// Assign
145184

146-
_settings.SetupGet(x => x.AcceptBrowserLanguage).Returns(true);
147185
var header = new HeaderDictionary(new Dictionary<string, StringValues>());
186+
187+
_settings.SetupGet(x => x.AcceptHeaderLanguage).Returns(true);
148188
_context.SetupGet(x => x.Request.Headers).Returns(header);
149189

150190
// Act
@@ -153,4 +193,17 @@ public void Constructor_NoBrowserLanguage_DefaultLanguageSet()
153193
// Assert
154194
Assert.AreEqual("en", _languageManager.Language);
155195
}
196+
197+
[Test]
198+
public void Constructor_BadDefaultLanguage_InvariantLanguageSet()
199+
{
200+
// Arrange
201+
_settings.SetupGet(x => x.DefaultLanguage).Returns("badlanguage");
202+
203+
// Act
204+
_languageManager = new LanguageManager(_settings.Object, _context.Object);
205+
206+
// Assert
207+
Assert.AreEqual("iv", _languageManager.Language);
208+
}
156209
}

src/Simplify.Web.Tests/Simplify.Web.Tests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>net7.0</TargetFramework>
3+
<TargetFramework>net8.0</TargetFramework>
44
<Nullable>enable</Nullable>
55
<WarningsAsErrors>nullable</WarningsAsErrors>
66

src/Simplify.Web/Modules/LanguageManager.cs

+42-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Globalization;
33
using System.Threading;
44
using Microsoft.AspNetCore.Http;
5+
using Simplify.System.Diagnostics;
56
using Simplify.Web.Settings;
67

78
namespace Simplify.Web.Modules;
@@ -16,6 +17,11 @@ public class LanguageManager : ILanguageManager
1617
/// </summary>
1718
public const string CookieLanguageFieldName = "language";
1819

20+
/// <summary>
21+
/// Language field name in request header
22+
/// </summary>
23+
public const string HeaderLanguageFieldName = "Accept-Language";
24+
1925
private readonly IResponseCookies _responseCookies;
2026

2127
/// <summary>
@@ -27,12 +33,12 @@ public LanguageManager(ISimplifyWebSettings settings, HttpContext context)
2733
{
2834
_responseCookies = context.Response.Cookies;
2935

30-
if (TrySetLanguageFromCookie(context))
36+
if (settings.AcceptCookieLanguage && TrySetLanguageFromCookie(context))
3137
return;
3238

33-
if (!settings.AcceptBrowserLanguage || (settings.AcceptBrowserLanguage && !TrySetLanguageFromRequestHeader(context)))
39+
if (!settings.AcceptHeaderLanguage || (settings.AcceptHeaderLanguage && !TrySetLanguageFromRequestHeader(context)))
3440
if (!SetCurrentLanguage(settings.DefaultLanguage))
35-
Language = "iv";
41+
SetInvariantCulture();
3642
}
3743

3844
/// <summary>
@@ -65,17 +71,44 @@ public bool SetCurrentLanguage(string language)
6571
{
6672
try
6773
{
68-
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
69-
Thread.CurrentThread.CurrentCulture = new CultureInfo(language);
70-
71-
Language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
74+
#if NET6_0
75+
CultureInfo.GetCultureInfo(language, true);
76+
#else
77+
if (!CultureExists(language))
78+
return false;
79+
#endif
7280

73-
return true;
7481
}
7582
catch
7683
{
7784
return false;
7885
}
86+
87+
Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
88+
Thread.CurrentThread.CurrentCulture = new CultureInfo(language);
89+
90+
Language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
91+
92+
return true;
93+
}
94+
95+
private void SetInvariantCulture()
96+
{
97+
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
98+
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
99+
100+
Language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
101+
}
102+
103+
private static bool CultureExists(string name)
104+
{
105+
var availableCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
106+
107+
foreach (CultureInfo culture in availableCultures)
108+
if (culture.Name.Equals(name))
109+
return true;
110+
111+
return false;
79112
}
80113

81114
private bool TrySetLanguageFromCookie(HttpContext context)
@@ -87,7 +120,7 @@ private bool TrySetLanguageFromCookie(HttpContext context)
87120

88121
private bool TrySetLanguageFromRequestHeader(HttpContext context)
89122
{
90-
var languages = context.Request.Headers["Accept-Language"];
123+
var languages = context.Request.Headers[HeaderLanguageFieldName];
91124

92125
if (languages.Count == 0)
93126
return false;

src/Simplify.Web/Modules/LanguageManagerProvider.cs

+6-8
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@ namespace Simplify.Web.Modules;
66
/// <summary>
77
/// Provides language manager provider
88
/// </summary>
9-
public class LanguageManagerProvider : ILanguageManagerProvider
9+
/// <remarks>
10+
/// Initializes a new instance of the <see cref="LanguageManagerProvider" /> class.
11+
/// </remarks>
12+
/// <param name="settings">The settings.</param>
13+
public class LanguageManagerProvider(ISimplifyWebSettings settings) : ILanguageManagerProvider
1014
{
11-
private readonly ISimplifyWebSettings _settings;
15+
private readonly ISimplifyWebSettings _settings = settings;
1216
private ILanguageManager? _languageManager;
1317

14-
/// <summary>
15-
/// Initializes a new instance of the <see cref="LanguageManagerProvider" /> class.
16-
/// </summary>
17-
/// <param name="settings">The settings.</param>
18-
public LanguageManagerProvider(ISimplifyWebSettings settings) => _settings = settings;
19-
2018
/// <summary>
2119
/// Creates the language manager instance.
2220
/// </summary>

0 commit comments

Comments
 (0)