FormatWith icon indicating copy to clipboard operation
FormatWith copied to clipboard

Define the CultureInfo of the format

Open ricardona opened this issue 3 years ago • 2 comments

We are using crozone/FormatWith to fill mail templates. These email templates must be sent in Spanish. However when trying to format the dates they appear in English.

Is there a mechanism to define the CultureInfo of the format?

            var template = "{d:dddd, MMMM dd, yyyy}";

            var stringDictionary = new Dictionary<string, object>
            {
                { "d", new DateTime(2025, 12, 31, 5, 10, 20) },
            };
            var result = template.FormatWith(template, stringDictionary);

            Assert.AreEqual("Wednesday, December 31, 2025", result);

Thanks in advance.

ricardona avatar Oct 06 '21 20:10 ricardona

Hi @ricardona, unfortunately there is currently no way to explicitly set the CultureInfo (or more generally, the IFormatProvider) while calling FormatWith. However, this is something I will look at adding in version 4.0.

In the meantime, I can see two possible workarounds:

  1. Format the date before passing it to format with

         // Get Spanish IFormatProvider
         IFormatProvider formatProvider = CultureInfo.CreateSpecificCulture("es");
    
         var template = "{d}";
    
         var stringDictionary = new Dictionary<string, object>
         {
             { "d", new DateTime(2025, 12, 31, 5, 10, 20).ToString("dddd, MMMM dd, yyyy", formatProvider) },
         };
         var result = template.FormatWith(stringDictionary);
    
  2. Set the current culture before calling FormatWith

         CultureInfo previousCulture = CultureInfo.CurrentCulture;
    
         // Set current culture to Spanish
         CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture("es");
    
         var template = "{d:dddd, MMMM dd, yyyy}";
    
         var stringDictionary = new Dictionary<string, object>
         {
             { "d", new DateTime(2025, 12, 31, 5, 10, 20) },
         };
         var result = template.FormatWith(stringDictionary);
    
         // Reset current culture back
         CultureInfo.CurrentCulture = previousCulture;
    

I hope one of these is suitable enough for now.

crozone avatar Oct 07 '21 05:10 crozone

@ricardona I've just remembered the third (and probably best) way to do this using FormatWith v3: Using FormattableWith()

// Get Spanish IFormatProvider
IFormatProvider formatProvider = CultureInfo.CreateSpecificCulture("es");

var template = "{d:dddd, MMMM dd, yyyy}";

var stringDictionary = new Dictionary<string, object>
{
    { "d", new DateTime(2025, 12, 31, 5, 10, 20) },
};
var result = template.FormattableWith(stringDictionary).ToString(formatProvider);

Output: "miércoles, diciembre 31, 2025"

This uses FormatWith to create an intermediate FormattableString, which can then be formatted using ToString(IFormatProvider). This is clean and I recommend this over the above two workarounds.

crozone avatar Oct 08 '21 06:10 crozone