Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce Culture Scope #7537

Merged
merged 10 commits into from
Nov 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using OrchardCore.DisplayManagement.Liquid;
using OrchardCore.Environment.Cache;
using OrchardCore.Liquid;
using OrchardCore.Localization;
using OrchardCore.Settings;
using YesSql;

Expand Down Expand Up @@ -391,19 +392,14 @@ private async Task GenerateContainerPathFromPattern(AutoroutePart part)
ContentItem = part.ContentItem
};

// We keep the current culture as a reference for later
var currentCulture = CultureInfo.CurrentUICulture;

_contentManager ??= _serviceProvider.GetRequiredService<IContentManager>();
var cultureAspect = await _contentManager.PopulateAspectAsync(part.ContentItem, new CultureAspect());

CultureInfo.CurrentUICulture = cultureAspect.Culture;

part.Path = await _liquidTemplateManager.RenderAsync(pattern, NullEncoder.Default, model,
scope => scope.SetValue("ContentItem", model.ContentItem));

// We reassign the proper culture to the current execution flow
CultureInfo.CurrentUICulture = currentCulture;
var cultureAspect = await _contentManager.PopulateAspectAsync(part.ContentItem, new CultureAspect());
using (CultureScope.Create(cultureAspect.Culture))
{
part.Path = await _liquidTemplateManager.RenderAsync(pattern, NullEncoder.Default, model,
scope => scope.SetValue("ContentItem", model.ContentItem));
}

part.Path = part.Path.Replace("\r", String.Empty).Replace("\n", String.Empty);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Globalization;

namespace OrchardCore.Localization
{
public sealed class CultureScope : IDisposable
{
private readonly CultureInfo _originalCulture;
private readonly CultureInfo _originalUICulture;

private CultureScope(CultureInfo culture, CultureInfo uiCulture)
{
Culture = culture;
hishamco marked this conversation as resolved.
Show resolved Hide resolved
UICulture = uiCulture;
_originalCulture = CultureInfo.CurrentCulture;
_originalUICulture = CultureInfo.CurrentUICulture;

SetCultures(culture, uiCulture);
}

public CultureInfo Culture { get; }

public CultureInfo UICulture { get; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hishamco i will approve your PR

But just one thing, i don't see any usage of these 2 public properties

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I point to where it's used, also we might to expose the original culture because may it's useful in some cases


public static CultureScope Create(string culture) => Create(culture, culture);

public static CultureScope Create(string culture, string uiCulture)
=> Create(CultureInfo.GetCultureInfo(culture), CultureInfo.GetCultureInfo(uiCulture));

public static CultureScope Create(CultureInfo culture) => Create(culture, culture);

public static CultureScope Create(CultureInfo culture, CultureInfo uiCulture) => new CultureScope(culture, uiCulture);

public void Dispose()
{
SetCultures(_originalCulture, _originalUICulture);
}
hishamco marked this conversation as resolved.
Show resolved Hide resolved

private static void SetCultures(CultureInfo culture, CultureInfo uiCulture)
{
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = uiCulture;
}
}
}
78 changes: 78 additions & 0 deletions test/OrchardCore.Tests/Localization/CultureScopeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Globalization;
using OrchardCore.Localization;
using Xunit;

namespace OrchardCore.Tests.Localization
{
public class CultureScopeTests
{
[Fact]
public void CultureScopeSetUICultureAutomaticallyIfNotSet()
{
// Arrange
var culture = "ar-YE";

// Act
using (var cultureScope = CultureScope.Create(culture))
{
// Assert
Assert.Equal(culture, cultureScope.Culture.Name);
Assert.Equal(culture, cultureScope.UICulture.Name);
}
}

[Fact]
public void CultureScopeRetreivesBothCultureAndUICulture()
{
// Arrange
var culture = "ar";
var uiCulture = "ar-YE";

// Act
using (var cultureScope = CultureScope.Create(culture, uiCulture))
{
// Assert
Assert.Equal(culture, cultureScope.Culture.Name);
Assert.Equal(uiCulture, cultureScope.UICulture.Name);
}
}

[Fact]
public void CultureScopeRetreivesTheOrginalCulturesAfterScopeEnded()
{
// Arrange
var culture = CultureInfo.CurrentCulture;
var uiCulture = CultureInfo.CurrentUICulture;

// Act
using (var cultureScope = CultureScope.Create("FR"))
{

}

// Assert
Assert.Equal(culture, CultureInfo.CurrentCulture);
Assert.Equal(uiCulture, CultureInfo.CurrentUICulture);
}

[Fact]
public void CultureScopeRetreivesTheOrginalCulturesIfExceptionOccurs()
{
// Arrange
var culture = CultureInfo.CurrentCulture;
var uiCulture = CultureInfo.CurrentUICulture;

// Act & Assert
Assert.ThrowsAsync<Exception>(() =>
{
using (var cultureScope = CultureScope.Create("FR"))
{
throw new Exception("Something goes wrong!!");
}
});
Assert.Equal(culture, CultureInfo.CurrentCulture);
Assert.Equal(uiCulture, CultureInfo.CurrentUICulture);
}
}
}
Loading