Why C#'s NumberFormatInfo returns the arabic percentage symbol for the french culture?

124 Views Asked by At

If you execute this C# code:

using System.Globalization;
using System;

public class HelloWorld
{
    public static void Main(string[] args)
    {
        CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("fr-FR");
        float p = 0.5f;
        Console.WriteLine(p.ToString("P0", CultureInfo.DefaultThreadCurrentCulture));
    }
}

The displayed result is: 50 ٪

Note that it uses the "٪" (Arabic percent sign U+066A) instead of the "%" (U+0025)

I could not find any resources explaining this behavior. Is this correct from a linguistic perspective?

Also, relevant to the question: "who" is responsible for implementing the appropriate cultures in C#? Is the OS or the .NET framework?

What I have tried

I tried different C# environments: I first found the issue inside a Unity project and then I created the above sample code and ran it in some online C# compiler tools. I am using a Windows 11 machine, but the behavior was reproduced in a Mac as well. I tried both specific France culture and neutral french one. The effect is the same in both

Thanks in advance,

1

There are 1 best solutions below

1
On

Also, relevant to the question: "who" is responsible for implementing the appropriate cultures in C#? Is the OS or the .NET framework?

.NET (Since .NET 5) .NET globalization and ICU

.NET Framework does't depend on the OS for its culture data. Instead, it has its own internal database of culture information that is used to ensure consistent behavior across different OS. This means that a .NET application will use the same culture data on Windows, Linux, and macOS, provided that the same version of the .NET runtime is used.

To fix your issue u can try set the correct percent symbol:

CultureInfo frenchCulture = new CultureInfo("fr-FR");
frenchCulture.NumberFormat.PercentSymbol = "%";
CultureInfo.DefaultThreadCurrentCulture = frenchCulture;
float p = 0.5f;
Console.WriteLine(p.ToString("P0", CultureInfo.DefaultThreadCurrentCulture));