Handlebars-Net / Handlebars.Net

A real .NET Handlebars engine
MIT License
1.22k stars 213 forks source link

[Question] Is FormatProvider used ? #534

Open StefH opened 1 year ago

StefH commented 1 year ago

Related to this old question: https://github.com/Handlebars-Net/Handlebars.Net/issues/344

The model:

var culture = CultureInfo.CreateSpecificCulture("en-US");
var jsonSettings = new JsonSerializerSettings
        {
            Culture = culture
        };
var model = JsonConvert.DeserializeObject("{ \"id\": 0.005 }", jsonSettings);

The template:

"test {{id}}"

Handlebars created like:

var config = new HandlebarsConfiguration
{
    FormatProvider = culture
};
var handlebars = HandlebarsDotNet.Handlebars.Create(config);

Execute the template:

var template = Handlebars.Compile(text);
var result = template(model);

And the result is:

"test 0,005" // <-- It's formatted using my local culture (Dutch) and not en-US?
StefH commented 1 year ago

@zjklee or @rexm : do you have an idea on this?

Nisden commented 1 year ago

@StefH I am pretty sure your issue is the fact that you are using an Dynamic Object or something similar as your model.

When running the following code all works as expected (Culture is respected when formatting the number)

    [Theory]
    [InlineData("en-us", "Test 0.5")]
    [InlineData("da-dk", "Test 0,5")]
    public void BasicCultureInfoFormatting(string culture, string expected)
    {
        var formatProvider = new CultureInfo(culture);
        var config = new HandlebarsConfiguration
        {
            FormatProvider = formatProvider
        };
        var handlebars = Handlebars.Create(config);

        var compiledTemplate = handlebars.Compile("Test {{number}}");

        var actual = compiledTemplate(new { number = 0.5 });

        Assert.Equal(expected, actual);
    }

However, if I try and replace my context with an dynamic object from Newtonsoft.Json.JsonConvert.DeserializeObject I start having the same issues.

Consider using DeserializeAnonymousType if possible

Newtonsoft.Json.JsonConvert.DeserializeAnonymousType("{ \"id\": 0.005 }", new
{
    id = 0
});
Nisden commented 1 year ago

@StefH Please ignore my first "solution" the actual solution is to deserialize into an ExpandObject, that still allows you to support dynamic values.

So your code should look like the following

var culture = CultureInfo.CreateSpecificCulture("en-US");
var model = JsonConvert.DeserializeObject<ExpandObject>("{ \"id\": 0.005 }");