Permalink
Browse files

Added localisation to Razor

  • Loading branch information...
1 parent 31ca17a commit 68050eed1a08d0115d0778707175a093800b6d9d @jchannon jchannon committed Dec 20, 2012
@@ -1,4 +1,5 @@
using System.Threading;
+using Nancy.Culture;
namespace Nancy.ViewEngines.Razor.Tests
{
@@ -19,11 +20,13 @@ public class RazorViewEngineFixture
private readonly IRazorConfiguration configuration;
private readonly FileSystemViewLocationProvider fileSystemViewLocationProvider;
private readonly IRootPathProvider rootPathProvider;
+ private readonly ILocationlisation locationlisation;
public RazorViewEngineFixture()
{
this.configuration = A.Fake<IRazorConfiguration>();
- this.engine = new RazorViewEngine(this.configuration);
+ this.locationlisation = A.Fake<ILocationlisation>();
+ this.engine = new RazorViewEngine(this.configuration, this.locationlisation);
var cache = A.Fake<IViewCache>();
A.CallTo(() => cache.GetOrAdd(A<ViewLocationResult>.Ignored, A<Func<ViewLocationResult, Func<NancyRazorViewBase>>>.Ignored))
@@ -381,7 +384,8 @@ public void Should_be_able_to_render_view_with_layout_and_optional_section_to_st
}
[Fact]
- public void Should_be_able_to_render_view_with_layout_and_optional_section_with_default_to_stream() {
+ public void Should_be_able_to_render_view_with_layout_and_optional_section_with_default_to_stream()
+ {
//Given
var location = FindView("ViewThatUsesLayoutAndOptionalSectionWithDefaults");
var stream = new MemoryStream();
@@ -398,7 +402,8 @@ public void Should_be_able_to_render_view_with_layout_and_optional_section_to_st
}
[Fact]
- public void Should_be_able_to_render_view_with_layout_and_optional_section_overriding_the_default_to_stream() {
+ public void Should_be_able_to_render_view_with_layout_and_optional_section_overriding_the_default_to_stream()
+ {
//Given
var location = FindView("ViewThatUsesLayoutAndOptionalSectionOverridingDefaults");
var stream = new MemoryStream();
@@ -413,7 +418,7 @@ public void Should_be_able_to_render_view_with_layout_and_optional_section_to_st
"<div>OptionalSectionOverride</div>",
"<div>ViewThatUsesLayoutAndOptionalSectionOverridingDefaults</div>");
}
-
+
[Fact]
public void Should_use_custom_view_base_with_csharp_views()
{
@@ -479,10 +484,10 @@ public void should_work_on_multiple_threads()
string.Empty,
"cshtml",
() =>
- {
- Thread.Sleep(500);
- return new StringReader(@"@{var x = ""test"";}<h1>Hello Mr. @x</h1>");
- });
+ {
+ Thread.Sleep(500);
+ return new StringReader(@"@{var x = ""test"";}<h1>Hello Mr. @x</h1>");
+ });
var wait = new ManualResetEvent(false);
@@ -497,7 +502,7 @@ public void should_work_on_multiple_threads()
});
var response = this.engine.RenderView(location, null, this.renderContext);
response.Contents.Invoke(stream);
-
+
wait.WaitOne(1000).ShouldBeTrue();
// Then
@@ -109,10 +109,12 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="CSharp\CSharpRazorViewRenderer.cs" />
+ <Compile Include="DefaultLocationlisation.cs" />
<Compile Include="DefaultRazorConfiguration.cs" />
<Compile Include="HelperResult.cs" />
<Compile Include="HtmlHelpers.cs" />
<Compile Include="IHtmlString.cs" />
+ <Compile Include="ILocationlisation.cs" />
<Compile Include="IRazorConfiguration.cs" />
<Compile Include="IRazorViewRenderer.cs" />
<Compile Include="ModelFinder.cs" />
@@ -6,6 +6,7 @@
using System.IO;
using System.Text;
using Nancy.Helpers;
+ using Nancy.Culture;
/// <summary>
/// Base class for nancy razor views.
@@ -77,14 +78,18 @@ public bool HasLayout
/// </summary>
public abstract void Execute();
+ public ILocationlisation Localisation { get; set; }
+
/// <summary>
/// Initializes the specified engine.
/// </summary>
/// <param name="engine">The engine.</param>
/// <param name="renderContext">The render context.</param>
/// <param name="model">The model.</param>
public virtual void Initialize(RazorViewEngine engine, IRenderContext renderContext, object model)
- { }
+ {
+ Localisation.CurrentCulture = renderContext.Context.Culture;
+ }
/// <summary>
/// Initializes a new instance of the <see cref="NancyRazorViewBase"/> class.
@@ -273,6 +278,8 @@ private static string HtmlEncode(object value)
}
}
+
+
/// <summary>
/// A strongly-typed view base.
/// </summary>
@@ -311,6 +318,7 @@ public override void Initialize(RazorViewEngine engine, IRenderContext renderCon
this.Model = (TModel)model;
this.Url = new UrlHelpers<TModel>(engine, renderContext);
this.ViewBag = renderContext.Context.ViewBag;
+ this.Localisation.CurrentCulture = renderContext.Context.Culture;
}
}
}
@@ -9,6 +9,9 @@
using System.Reflection;
using System.Web.Razor;
using System.Web.Razor.Parser.SyntaxTree;
+ using System.Collections;
+ using System.Resources;
+ using Nancy.Culture;
using Nancy.Bootstrapper;
using Nancy.Responses;
@@ -19,6 +22,7 @@
public class RazorViewEngine : IViewEngine, IDisposable
{
private readonly IRazorConfiguration razorConfiguration;
+ private readonly ILocationlisation locationlisation;
private readonly IEnumerable<IRazorViewRenderer> viewRenderers;
private readonly object compileLock = new object();
@@ -36,7 +40,7 @@ public IEnumerable<string> Extensions
/// Initializes a new instance of the <see cref="RazorViewEngine"/> class.
/// </summary>
/// <param name="configuration">The <see cref="IRazorConfiguration"/> that should be used by the engine.</param>
- public RazorViewEngine(IRazorConfiguration configuration)
+ public RazorViewEngine(IRazorConfiguration configuration, ILocationlisation locationlisation)
{
this.viewRenderers = new List<IRazorViewRenderer>
{
@@ -45,6 +49,7 @@ public RazorViewEngine(IRazorConfiguration configuration)
};
this.razorConfiguration = configuration;
+ this.locationlisation = locationlisation;
}
/// <summary>
@@ -131,7 +136,7 @@ private Func<NancyRazorViewBase> GetCompiledViewFactory(string extension, TextRe
var engine = this.GetRazorTemplateEngine(renderer.Host);
- var razorResult = engine.GenerateCode(reader, sourceFileName:"placeholder");
+ var razorResult = engine.GenerateCode(reader, sourceFileName: "placeholder");
var viewFactory = this.GenerateRazorViewFactory(renderer.Provider, razorResult, referencingAssembly, renderer.Assemblies, passedModelType, viewLocationResult);
@@ -227,10 +232,10 @@ private Func<NancyRazorViewBase> GenerateRazorViewFactory(CodeDomProvider codePr
private static string BuildErrorMessages(IEnumerable<CompilerError> errors)
{
return errors.Select(error => String.Format(
- "[{0}] Line: {1} Column: {2} - {3} (<a class='LineLink' href='#{1}'>show</a>)",
- error.ErrorNumber,
- error.Line,
- error.Column,
+ "[{0}] Line: {1} Column: {2} - {3} (<a class='LineLink' href='#{1}'>show</a>)",
+ error.ErrorNumber,
+ error.Line,
+ error.Column,
error.ErrorText)).Aggregate((s1, s2) => s1 + "<br/>" + s2);
}
@@ -342,16 +347,18 @@ private NancyRazorViewBase GetOrCompileView(ViewLocationResult viewLocationResul
var view = viewFactory.Invoke();
+ view.Localisation = this.locationlisation;
+
view.Code = string.Empty;
return view;
}
private NancyRazorViewBase GetViewInstance(ViewLocationResult viewLocationResult, IRenderContext renderContext, Assembly referencingAssembly, dynamic model)
{
- var modelType = (model == null) ? null : model.GetType();
+ var modelType = (model == null) ? null : model.GetType();
- var view =
+ var view =
this.GetOrCompileView(viewLocationResult, renderContext, referencingAssembly, modelType);
view.Initialize(this, renderContext, model);
@@ -13,7 +13,14 @@ public class RazorViewEngineApplicationRegistrations : IApplicationRegistrations
/// </summary>
public IEnumerable<TypeRegistration> TypeRegistrations
{
- get { return new[] { new TypeRegistration(typeof(IRazorConfiguration), typeof(DefaultRazorConfiguration)) }; }
+ get
+ {
+ return new[]
+ {
+ new TypeRegistration(typeof(IRazorConfiguration), typeof(DefaultRazorConfiguration)),
+ new TypeRegistration(typeof(ILocationlisation), typeof(DefaultLocationlisation))
+ };
+ }
}
/// <summary>
@@ -30,7 +30,7 @@ public void Initialise(NancyConventions conventions)
return Tuple.Create(false, "The view conventions cannot be null.");
}
- return (conventions.ViewLocationConventions.Count > 0) ?
+ return (conventions.ViewLocationConventions.Count > 0) ?
Tuple.Create(true, string.Empty) :
Tuple.Create(false, "The view conventions cannot be empty.");
}
@@ -39,6 +39,17 @@ private static void ConfigureViewLocationConventions(NancyConventions convention
{
conventions.ViewLocationConventions = new List<Func<string, object, ViewLocationContext, string>>
{
+ (viewName, model, viewLocationContext) =>{
+ if (string.IsNullOrEmpty(viewLocationContext.ModulePath))
+ {
+ return string.Empty;
+ }
+
+ var path = viewLocationContext.ModulePath.TrimStart(new[] { '/' });
+
+ return string.Concat("views/", path, "/", viewLocationContext.ModuleName, "/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 0 Handles: views / *modulepath* / *modulename* / *viewname*
(viewName, model, viewLocationContext) =>{
if (string.IsNullOrEmpty(viewLocationContext.ModulePath))
@@ -51,6 +62,17 @@ private static void ConfigureViewLocationConventions(NancyConventions convention
return string.Concat("views/", path, "/", viewLocationContext.ModuleName, "/", viewName);
},
+ (viewName, model, viewLocationContext) =>{
+ if (string.IsNullOrEmpty(viewLocationContext.ModulePath))
+ {
+ return string.Empty;
+ }
+
+ var path = viewLocationContext.ModulePath.TrimStart(new[] { '/' });
+
+ return string.Concat(path, "/", viewLocationContext.ModuleName, "/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 1 Handles: *modulepath* / *modulename* / *viewname*
(viewName, model, viewLocationContext) =>{
if (string.IsNullOrEmpty(viewLocationContext.ModulePath))
@@ -63,31 +85,55 @@ private static void ConfigureViewLocationConventions(NancyConventions convention
return string.Concat(path, "/", viewLocationContext.ModuleName, "/", viewName);
},
+ (viewName, model, viewLocationContext) =>{
+ return string.IsNullOrEmpty(viewLocationContext.ModulePath) ? string.Empty : string.Concat("views/", viewLocationContext.ModulePath.TrimStart(new[] { '/' }), "/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 2 Handles: views / *modulepath* / *viewname*
(viewName, model, viewLocationContext) =>{
return string.IsNullOrEmpty(viewLocationContext.ModulePath) ? string.Empty : string.Concat("views/", viewLocationContext.ModulePath.TrimStart(new[] {'/'}), "/", viewName);
},
+ (viewName, model, viewLocationContext) =>{
+ return string.IsNullOrEmpty(viewLocationContext.ModulePath) ? string.Empty : string.Concat(viewLocationContext.ModulePath.TrimStart(new[] { '/' }), "/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 3 Handles: *modulepath* / *viewname*
(viewName, model, viewLocationContext) =>{
return string.IsNullOrEmpty(viewLocationContext.ModulePath) ? string.Empty : string.Concat(viewLocationContext.ModulePath.TrimStart(new[] { '/' }), "/", viewName);
},
+ (viewName, model, viewLocationContext) => {
+ return string.Concat("views/", viewLocationContext.ModuleName, "/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 4 Handles: views / *modulename* / *viewname*
(viewName, model, viewLocationContext) => {
return string.Concat("views/", viewLocationContext.ModuleName, "/", viewName);
},
+ (viewName, model, viewLocationContext) => {
+ return string.Concat(viewLocationContext.ModuleName, "/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 5 Handles: *modulename* / *viewname*
(viewName, model, viewLocationContext) => {
return string.Concat(viewLocationContext.ModuleName, "/", viewName);
},
+ (viewName, model, viewLocationContext) => {
+ return string.Concat("views/", viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 6 Handles: views / *viewname*
(viewName, model, viewLocationContext) => {
return string.Concat("views/", viewName);
},
+ (viewName, model, viewLocationContext) => {
+ return string.Concat(viewName, "-", viewLocationContext.Context.Culture);
+ },
+
// 7 Handles: *viewname*
(viewName, model, viewLocationContext) => {
return viewName;

0 comments on commit 68050ee

Please sign in to comment.