Software Internationalization Summary: formatting and conversion between numbers and strings

Source: Internet
Author: User

I. Internationalization-Example of formatting numbers as strings

In the past, it was generally finished to deal with numbers directly using tostring (), but it was not easy to use software that needed to be internationalized. For example, in some countries, the amount of sub-bits is not a comma but a full stop, the decimal point is not a period but a comma. Therefore, to display the number in the correct string form in front of the Chinese, you need to use a clear method.

In fact, the tostring () method of numbers has multiple reloads, which are used to correctly format the numbers of countries in international countries.

1. First look at a simpleProgramDemo

Using system;
Using system. Collections. Generic;
Using system. LINQ;
Using system. text;
Using system. Globalization;

Namespace international class library Test
{
Class Program
{
Static void main (string [] ARGs)
{
Decimal input = 12345678;
Cultureinfo culture = new cultureinfo ("km-Kh ");
// C or C represents the currency
Console. writeline (input. tostring ("C", culture); // 12,345,678.00?
// N or N indicates a number.
Console. writeline (input. tostring ("N", culture); // 12345,678.00
Console. readkey ();
}
}
}

2. Standard for formatting numbers into strings
C and C represent currencies, and N represent numbers.

 
"C" or "C" currency result: currency value.
123.456 ("C", en-US)-> $123.46
123.456 ("C", fr-fr)-> €
123.456 ("C", ja-JP)-> ¥ 123
-123.456 ("C3", en-US)-> ($123.456)
-123.456 ("C3", fr-fr)->-123,456 €
-123.456 ("C3", ja-JP)->-¥ 123. 456

The result of "D" or "D" decimal is an integer number, and the negative number is optional.
Supported by the following types: integer only.
1234 ("D")-> 1234
-1234 ("D6")->-001234

3. decompile the tostring () method of the decimal class. SeeSource code.

3.1 reload methods of decimal tostring ()
In the mscorlib. dll library. SourceCodeAs follows:
Public override string tostring ()
{
Return number. formatdecimal (this, null, numberformatinfo. currentinfo );
}
Public String tostring (string format)
{
Return number. formatdecimal (this, format, numberformatinfo. currentinfo );
}
Public String tostring (iformatprovider provider)
{
Return number. formatdecimal (this, null, numberformatinfo. getinstance (provider ));
}
Public String tostring (string format, iformatprovider provider)
{
Return number. formatdecimal (this, format, numberformatinfo. getinstance (provider ));
}

Public static numberformatinfo getinstance (iformatprovider formatprovider)
{
Numberformatinfo numinfo;
Cultureinfo info2 = formatprovider as cultureinfo;
If (info2! = NULL )&&! Info2.m _ isinherited)
{
Numinfo = info2.numinfo;
If (numinfo! = NULL)
{
Return numinfo;
}
Return info2.numberformat;
}
Numinfo = formatprovider as numberformatinfo;
If (numinfo! = NULL)
{
Return numinfo;
}
If (formatprovider! = NULL)
{
Numinfo = formatprovider. getformat (typeof (numberformatinfo) as numberformatinfo;
If (numinfo! = NULL)
{
Return numinfo;
}
}
Return currentinfo;
}

3.2 iformatprovider Interface
[Comvisible (true)]
Public interface iformatprovider
{
// Methods
Object getformat (type formattype );
}

3.3 iformatprovider in cultureinfo
Public class cultureinfo: icloneable, iformatprovider
{

Public Virtual Object getformat (type formattype)
{
If (formattype = typeof (numberformatinfo ))
{
Return this. numberformat;
}
If (formattype = typeof (datetimeformatinfo ))
{
Return this. datetimeformat;
}
Return NULL;
}
}

3.4 iformatprovider in numberformatinfo
[Serializable, comvisible (true)]
Public sealed class numberformatinfo: icloneable, iformatprovider
{
Public object getformat (type formattype)
{
If (formattype! = Typeof (numberformatinfo ))
{
Return NULL;
}
Return this;
}
}

Formatdecimal In the 3.5 Number
Internal class number
{
// Fields
Private const int int32precision = 10;
Private const int int64precision = 0x13;
Private const int numbermaxdigits = 50;
Private const int uint32precision = 10;
Private const int uint64precision = 20;

// Methods
Private Number ();
[Methodimpl (methodimploptions. internalcall)]
Public static extern string formatdecimal (decimal value, string format, numberformatinfo info );
[Methodimpl (methodimploptions. internalcall)]

3.5.1 what does the C # extern modifier mean?
The C # extern modifier is used to declare that member functions implemented outside the Assembly are often used to call system API functions (through dllimport ). Note: when using the C # extern modifier and dllimport together, you must add a static modifier. It can also be used for calling components of different versions of the same assembly (using extern to declare aliases) it cannot be used together with the abstract modifier.

Dllimport ("avifil32.dll")]
Private Static extern void avifileinit ();
That is to say, this method is implemented in a class other than the declared class.

3.6 numberformatinfo list of all Members
[Serializable, comvisible (true)]
Public sealed class numberformatinfo: icloneable, iformatprovider
{
// Fields
Internal string ansicurrencysymbol;
Internal int currencydecimaldigits;
Internal string currencydecimalseparator;
Internal string currencygroupseparator;
Internal int [] currencygroupsizes;
Internal int currencynegativepattern;
Internal int currencypositivepattern;
Internal string currencysymbol;
[Optionalfield (versionadded = 2)]
Internal int digitsubstitution;
Private const numberstyles invalidnumberstyles = ~ (Numberstyles. hexnumber | numberstyles. Capacity | numberstyles. allowexponent | numberstyles. Capacity | numberstyles. allowdecimalpoint | numberstyles. Capacity | numberstyles. Capacity | numberstyles. capacity );
Private Static numberformatinfo invariantinfo;
Internal bool isreadonly;
Internal int m_dataitem;
Internal bool m_useuseroverride;
Internal string nansymbol;
[Optionalfield (versionadded = 2)]
Internal string [] nativedigits;
Internal string negativeinfinitysymbol;
Internal string negativesign;
Internal int numberdecimaldigits;
Internal string numberdecimalseparator;
Internal string numbergroupseparator;
Internal int [] numbergroupsizes;
Internal int numbernegativepattern;
Internal int percentdecimaldigits;
Internal string percentdecimalseparator;
Internal string percentgroupseparator;
Internal int [] percentgroupsizes;
Internal int percentnegativepattern;
Internal int percentpositivepattern;
Internal string percentsymbol;
Internal string permillesymbol;
Internal string positiveinfinitysymbol;
Internal string positivesign;
Internal bool validforparseascurrency;
Internal bool validforparseasnumber;

// Methods
Public numberformatinfo ();
Internal numberformatinfo (culturetablerecord );
Internal void checkgroupsize (string propname, int [] groupsize );
Public object clone ();
Public object getformat (type formattype );
Public static numberformatinfo getinstance (iformatprovider formatprovider );
[Ondeserialized]
Private void ondeserialized (streamingcontext CTX );
[Ondeserializing]
Private void ondeserializing (streamingcontext CTX );
[Onserializing]
Private void onserializing (streamingcontext CTX );
Public static numberformatinfo readonly (numberformatinfo NFI );
Internal static void validateparsestylefloatingpoint (numberstyles style );
Internal static void validateparsestyleinteger (numberstyles style );
Private void verifydecimalseparator (string decsep, string propertyname );
Private void verifydigitsubstitution (digitshapes digitsub, string propertyname );
Private void verifygroupseparator (string groupsep, string propertyname );
Private void verifynativedigits (string [] nativedig, string propertyname );
Private void verifywritable ();

// Properties
Public int currencydecimaldigits {Get; set ;}
Public String currencydecimalseparator {Get; set ;}
Public String currencygroupseparator {Get; set ;}
Public int [] currencygroupsizes {Get; set ;}
Public int currencynegativepattern {Get; set ;}
Public int currencypositivepattern {Get; set ;}
Public String currencysymbol {Get; set ;}
Public static numberformatinfo currentinfo {Get ;}
[Comvisible (false)]
Public digitshapes digitsubstitution {Get; set ;}
Public static numberformatinfo invariantinfo {Get ;}
Public bool isreadonly {Get ;}
Public String nansymbol {Get; set ;}
[Comvisible (false)]
Public String [] nativedigits {Get; set ;}
Public String negativeinfinitysymbol {Get; set ;}
Public String negativesign {Get; set ;}
Public int numberdecimaldigits {Get; set ;}
Public String numberdecimalseparator {Get; set ;}
Public String numbergroupseparator {Get; set ;}
Public int [] numbergroupsizes {Get; set ;}
Public int numbernegativepattern {Get; set ;}
Public int percentdecimaldigits {Get; set ;}
Public String percentdecimalseparator {Get; set ;}
Public String percentgroupseparator {Get; set ;}
Public int [] percentgroupsizes {Get; set ;}
Public int percentnegativepattern {Get; set ;}
Public int percentpositivepattern {Get; set ;}
Public String percentsymbol {Get; set ;}
Public String permillesymbol {Get; set ;}
Public String positiveinfinitysymbol {Get; set ;}
Public String positivesign {Get; set ;}
}

 

There are important attributes such as numbergroupseparator, numberdecimalseparator, decimal point separator, currencydecimalseparator, and currencygroupseparator.

 

4. parse the previous demo program
The iformatprovider interface has a getformat method.

When console. writeline (input. tostring ("C", culture) is executed; // 12,345,678.00?

, Execute the following method:
Public String tostring (string format, iformatprovider provider)
{
Return number. formatdecimal (this, format, numberformatinfo. getinstance (provider ));
}

Then run the getinstance method to obtain the numberformatinfo object.
Public static numberformatinfo getinstance (iformatprovider formatprovider)
{
Numberformatinfo numinfo;
Cultureinfo info2 = formatprovider as cultureinfo;
If (info2! = NULL )&&! Info2.m _ isinherited)
{
Numinfo = info2.numinfo;
If (numinfo! = NULL)
{
Return numinfo;
}
Return info2.numberformat;
}
Numinfo = formatprovider as numberformatinfo;
If (numinfo! = NULL)
{
Return numinfo;
}
If (formatprovider! = NULL)
{
Numinfo = formatprovider. getformat (typeof (numberformatinfo) as numberformatinfo;
If (numinfo! = NULL)
{
Return numinfo;
}
}
Return currentinfo;
}

Finally, RUN number. formatdecimal (this, format, numberformatinfo. getinstance (provider ))

That is, the value to be formatted, the format identifier C or N, and numberformat (here there is a number thousands separator numbergroupseparator, the decimal separator numberdecimalseparator, the currency decimal separator and the thousands separator currencydecimalseparator, currency)

However, number. formatdecimal is an external function. The specific implementation cannot be found and can only be followed here.

5. Summary
If you want to convert a number to an ideal format, you must pass in C or N as well as culture. If you do not transfer a number, the system will also use the default culture in the work thread.

 

Ii. Internationalization-Example of converting strings into numbers
In general, for a string that represents a number, use convert. todecimal or decimal. tryparse can convert it to the numeric type. However, if a country like Vietnam or Germany uses a full period and a comma to indicate the decimal point, if you want to convert this string to a number using todecimal, it will be a little troublesome.

For example, if a Vietnamese string "333.444.555, 333" is actually a number 333444555.333, how can we restore it to a correct number?

1. Program demo
String inputstring = "333.444.555, 333 ";
Decimal decimalinput = convert. todecimal (inputstring );
Result: decimal. tryparse = 333444,555.00.

The system reports an incorrect string format.
 

2. Solution
Overload method using todecimal: public static decimal todecimal (string value, iformatprovider provider)

String inputstring = "333.444.555, 333 ";
Decimal decimalinput = convert. todecimal (inputstring, new cultureinfo ("Vi-VN "));
Console. writeline ("Convert. todecimal =" + decimalinput. tostring ("N", culture ));

Result: 333.444.555, 33

3. A better way is to use decimal. tryparse. If the conversion fails, no exception is reported.
If (decimal. tryparse (inputstring, numberstyles. Number, new cultureinfo ("Vi-VN"), Out decimalinput ))
{
Console. writeline ("decimal. tryparse =" + decimalinput. tostring ("N", culture ));
}

4. Summary
String (in general, it may have a format, such as a decimal point). If you want to convert it to a number correctly, you also need to input a culture.

 

Iii. Summary

In international software, formatting and conversion between numbers and strings must be intentionally added with the cultural cultureinfo dimension. software without international requirements does not seem to have this dimension, all of them have default cultural participation, but they have not noticed its existence.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.