Improve ViewLocalizer resource look-up semantics:
- Always prepend with application name and let underlying `IStringLocalizerFactory` do the name gymnastics - Use ExecutingFilePath instead of view name - Trim off the file extension (so your resource doesn't have to have ".cshtml" in its name) - Improved doc comments - Added tests to cover ViewLocalizer behavior - #3718 - #2767
This commit is contained in:
parent
d77655fb73
commit
1529c868f2
|
|
@ -4,7 +4,7 @@
|
|||
namespace Microsoft.AspNet.Mvc.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// A service that provides localized strings for views.
|
||||
/// Represents a type that provides HTML-aware localization for views.
|
||||
/// </summary>
|
||||
public interface IViewLocalizer : IHtmlLocalizer
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.ViewFeatures.Internal;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
|
@ -12,7 +14,8 @@ using Microsoft.Extensions.PlatformAbstractions;
|
|||
namespace Microsoft.AspNet.Mvc.Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="IHtmlLocalizer"/> implementation that provides localized strings for views.
|
||||
/// An <see cref="IViewLocalizer"/> implementation that derives the resource location from the executing view's
|
||||
/// file path.
|
||||
/// </summary>
|
||||
public class ViewLocalizer : IViewLocalizer, ICanHasViewContext
|
||||
{
|
||||
|
|
@ -93,12 +96,30 @@ namespace Microsoft.AspNet.Mvc.Localization
|
|||
throw new ArgumentNullException(nameof(viewContext));
|
||||
}
|
||||
|
||||
var baseName = viewContext.View.Path.Replace('/', '.').Replace('\\', '.');
|
||||
if (baseName.StartsWith(".", StringComparison.OrdinalIgnoreCase))
|
||||
// Given a view path "/Views/Home/Index.cshtml" we want a baseName like "MyApplication.Views.Home.Index"
|
||||
|
||||
var path = viewContext.ExecutingFilePath;
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
baseName = baseName.Substring(1);
|
||||
path = viewContext.View.Path;
|
||||
}
|
||||
|
||||
// Trim the file extension from the end of the path
|
||||
if (!string.IsNullOrEmpty(path) && Path.HasExtension(path))
|
||||
{
|
||||
var extension = Path.GetExtension(path);
|
||||
path = path.Substring(0, path.Length - extension.Length);
|
||||
}
|
||||
|
||||
Debug.Assert(!string.IsNullOrEmpty(path), "Couldn't determine a path for the view");
|
||||
|
||||
var baseName = path.Replace('/', '.').Replace('\\', '.');
|
||||
baseName = baseName.TrimStart('.');
|
||||
|
||||
// Prepend the application name
|
||||
baseName = _applicationName + "." + baseName;
|
||||
|
||||
_localizer = _localizerFactory.Create(baseName, _applicationName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,39 @@ namespace Microsoft.AspNet.Mvc.Localization.Test
|
|||
{
|
||||
public class ViewLocalizerTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("TestApplication", "Views/Home/Index.cshtml", "Views/Home/Index.cshtml", "TestApplication.Views.Home.Index")]
|
||||
[InlineData("TestApplication.Web", "Views/Home/Index.cshtml", "Views/Home/Index.cshtml", "TestApplication.Web.Views.Home.Index")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.cshtml", "Views/Shared/_Layout.cshtml", "TestApplication.Views.Shared._Layout")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.cshtml", "Views/Shared/_MyPartial.cshtml", "TestApplication.Views.Shared._MyPartial")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.cshtml", "Views/Home/_HomePartial.cshtml", "TestApplication.Views.Home._HomePartial")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.cshtml", null, "TestApplication.Views.Home.Index")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.txt", null, "TestApplication.Views.Home.Index")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.cshtml", "", "TestApplication.Views.Home.Index")]
|
||||
[InlineData("TestApplication", "Views/Home/Index.txt", "", "TestApplication.Views.Home.Index")]
|
||||
public void ViewLocalizer_LooksForCorrectResourceBaseNameLocation(string appName, string viewPath, string executingPath, string expectedBaseName)
|
||||
{
|
||||
// Arrange
|
||||
var applicationEnvironment = new Mock<IApplicationEnvironment>();
|
||||
applicationEnvironment.Setup(a => a.ApplicationName).Returns(appName);
|
||||
var htmlLocalizerFactory = new Mock<IHtmlLocalizerFactory>(MockBehavior.Loose);
|
||||
var view = new Mock<IView>();
|
||||
view.Setup(v => v.Path).Returns(viewPath);
|
||||
var viewContext = new ViewContext();
|
||||
viewContext.ExecutingFilePath = executingPath;
|
||||
viewContext.View = view.Object;
|
||||
var viewLocalizer = new ViewLocalizer(htmlLocalizerFactory.Object, applicationEnvironment.Object);
|
||||
|
||||
// Act
|
||||
viewLocalizer.Contextualize(viewContext);
|
||||
|
||||
// Assert
|
||||
htmlLocalizerFactory.Verify(h => h.Create(
|
||||
It.Is<string>(baseName => baseName == expectedBaseName),
|
||||
It.Is<string>(location => location == appName)
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ViewLocalizer_UseIndexer_ReturnsLocalizedHtmlString()
|
||||
{
|
||||
|
|
@ -29,7 +62,7 @@ namespace Microsoft.AspNet.Mvc.Localization.Test
|
|||
htmlLocalizer.Setup(h => h["Hello"]).Returns(localizedString);
|
||||
|
||||
var htmlLocalizerFactory = new Mock<IHtmlLocalizerFactory>();
|
||||
htmlLocalizerFactory.Setup(h => h.Create("example", "TestApplication"))
|
||||
htmlLocalizerFactory.Setup(h => h.Create("TestApplication.example", "TestApplication"))
|
||||
.Returns(htmlLocalizer.Object);
|
||||
|
||||
var viewLocalizer = new ViewLocalizer(htmlLocalizerFactory.Object, applicationEnvironment.Object);
|
||||
|
|
@ -62,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.Localization.Test
|
|||
|
||||
var htmlLocalizerFactory = new Mock<IHtmlLocalizerFactory>();
|
||||
htmlLocalizerFactory.Setup(
|
||||
h => h.Create("example", "TestApplication")).Returns(htmlLocalizer.Object);
|
||||
h => h.Create("TestApplication.example", "TestApplication")).Returns(htmlLocalizer.Object);
|
||||
|
||||
var viewLocalizer = new ViewLocalizer(htmlLocalizerFactory.Object, applicationEnvironment.Object);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue