そしてそう
もちろん、正直な人として、私はこのトピックに関するすべてのコメントを読み、この式のリストを見つけました。 言語のサポートを追加するには、リストから式をコピーするだけです。
その後、既製のソリューションを探すことにしました。 PawnHunter [C#] IFormatProviderから可算名詞のソリューションを見つけました。 おもしろいだけでなく、言葉で数字を書く機能もあります。 しかし、複雑さの欠如は言語の追加です。 著者は当初ロシア語を愛用しており、ロシアの規則に従って3つの形式の数字を探しています。 最初の2つのフォームが一致するため、彼は英語で幸運でしたが、3番目のフォームは必要ありません。 優れた式とフォームの数を持つ他の言語は失敗します。
私のソリューションに十分な資料があったので、私はこれ以上詳しく調べませんでした。アイデア、公式、既製の例です。
使用の構文。
C#:
NumeralsFormatter formatter = new NumeralsFormatter ( ) ; //
formatter. CultureInfo = new CultureInfo ( "ru-RU" ) ; //
Int32 files = 0 , folders = 5 ;
String exResult = String . Format ( formatter, "{0:W| |1 |% |% } {1:W|0 |1 |% |% }." , files, folders ) ; //
String shortResult = String . Format ( formatter, "{0:W|% (,,) (,,)} {1:W|% (,,}." , files, folders ) ; //
Javascript
// CultureInfo.name
var files = 0 , folders = 5 ;
var exResult = String. wformat ( "{0:W| |1 |% |% } {1:W|0 |1 |% |% }." , files , folders ) ; //
var shortResult = String. wformat ( "{0:W|% (,,) (,,)} {1:W|% (,,}." , files , folders ) ; //
ご覧のとおり、構文は元の記事から取られており、書式設定のみがString.Formatに合わせて調整されています。 さらに、短縮版はPawnHunterから借用しています。
%文字は、数値の置換を担当します。
次のことに注意してください。 展開されたバージョンでは、最初に来るゼロ値に対して、単語形式がもう1つ送信されます。 省略されたゼロ形式はありません。フォームは式によって計算されます。
|などの特殊文字を使用するには %複製する必要がある|| %%。 省略形の場合は、プラス((s))。
そして最後に、ソースコードを提供します。
using System ;
using System.Text ;
using System.Globalization ;
public class NumeralsFormatter : IFormatProvider, ICustomFormatter
{
public CultureInfo CultureInfo ;
public NumeralsFormatter ( ) : this ( System. Threading . Thread . CurrentThread . CurrentCulture ) { }
public NumeralsFormatter ( CultureInfo cultureInfo )
{
this . CultureInfo = cultureInfo ;
}
public Object GetFormat ( Type formatType )
{
return formatType == typeof ( ICustomFormatter ) ? this : CultureInfo. GetFormat ( formatType ) ;
}
private String FormatUnknown ( String format, Object arg, IFormatProvider formatProvider )
{
IFormattable formattable = arg as IFormattable ;
if ( formattable == null ) return arg. ToString ( ) ;
return formattable. ToString ( format, formatProvider ) ;
}
public Boolean IsNumeralType ( Type type )
{
return type == typeof ( Int32 )
|| type == typeof ( UInt32 )
|| type == typeof ( Double )
|| type == typeof ( Single )
|| type == typeof ( Decimal )
|| type == typeof ( Int64 )
|| type == typeof ( UInt64 )
|| type == typeof ( Int16 )
|| type == typeof ( UInt16 )
|| type == typeof ( Byte )
|| type == typeof ( SByte )
|| type == typeof ( Char ) ;
}
public String Format ( String format, Object arg, IFormatProvider formatProvider )
{
if ( format == null || ! IsNumeralType ( arg. GetType ( ) ) )
return FormatUnknown ( format, arg, formatProvider ) ;
String [ ] forms = format. Replace ( "||" , " \u fffc" ) . Split ( '|' ) ;
if ( forms [ 0 ] . ToUpper ( ) == "W" )
{
Int32 idxForm = - 1 ;
Double n = Math. Abs ( Convert. ToDouble ( arg ) ) ;
// translate.sourceforge.net/wiki/l10n/pluralforms
switch ( CultureInfo. Parent . Name )
{
case "en" : idxForm = ( n != 1 ? 1 : 0 ) ; break ;
case "ru" : idxForm = ( n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 ) ; break ;
}
String form = null ;
if ( idxForm != - 1 )
{
if ( forms. Length > 2 ) // extended form
{
idxForm = n == 0 ? 1 : idxForm + 2 ;
form = forms [ idxForm ] . Replace ( ' \u fffc' , '|' ) ;
}
else if ( forms. Length > 1 )
{
StringBuilder sb = new StringBuilder ( ) ;
forms = forms [ 1 ] . Replace ( ' \u fffc' , '|' ) . Replace ( "((" , " \u fd3e" ) . Replace ( "))" , " \u fd3f" ) . Split ( '(' ) ;
int i = 0 ;
for ( ; i < forms. Length - 1 ; ++ i )
{
sb. Append ( forms [ i ] ) ;
Int32 rp = forms [ i + 1 ] . IndexOf ( ')' ) ;
if ( rp != - 1 )
{
sb. Append ( forms [ i + 1 ] . Substring ( 0 , rp ) . Split ( ',' ) [ idxForm ] ) ;
forms [ i + 1 ] = forms [ i + 1 ] . Substring ( rp + 1 ) ;
}
}
sb. Append ( forms [ i ] ) ;
form = sb. Replace ( ' \u fd3e' , '(' ) . Replace ( ' \u fd3f' , ')' ) . ToString ( ) ;
}
}
if ( form != null )
return form. Replace ( "%%" , " \u fffc" ) . Replace ( "%" , ( ( IFormattable ) arg ) . ToString ( null , CultureInfo ) ) . Replace ( ' \u fffc' , '%' ) ;
}
return FormatUnknown ( format, arg, formatProvider ) ;
}
}
String. wformat = function ( f )
{
var a = arguments ; return f. replace ( /{(\d+)(.*?)}/ig , function ( $ 0 , $ 1 , $ 2 )
{
var arg = a [ Number ( $ 1 ) + 1 ] ;
var n = Math. abs ( arg ) ;
if ( $ 2 && ! isNaN ( n ) )
{
var forms = $2. replace ( /\|\|/gm , ' \u fffc' ) . split ( '|' ) ;
if ( forms [ 0 ] . toUpperCase ( ) == ":W" )
{
var idxForm = - 1 ;
switch ( CultureInfo. name . split ( '-' ) [ 0 ] )
{
case "en" : idxForm = ( n != 1 ? 1 : 0 ) ; break ;
case "ru" : idxForm = ( n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 ) ; break ;
}
var form = null ;
if ( idxForm != - 1 )
{
if ( forms. length > 2 ) // extended form
{
idxForm = n == 0 ? 1 : idxForm + 2 ;
form = forms [ idxForm ] . replace ( /\ufffc/gm , '|' ) ;
}
else if ( forms. length > 1 )
{
var sb = [ ] ;
forms = forms [ 1 ] . replace ( /\ufffc/gm , '|' ) . replace ( /\(\(/gm , ' \u fd3e' ) . replace ( /\)\)/gm , ' \u fd3f' ) . split ( '(' ) ;
var i = 0 ;
for ( ; i < forms. length - 1 ; ++ i )
{
sb. push ( forms [ i ] ) ;
var rp = forms [ i + 1 ] . indexOf ( ')' ) ;
if ( rp != - 1 )
{
sb. push ( forms [ i + 1 ] . substring ( 0 , rp ) . split ( ',' ) [ idxForm ] ) ;
forms [ i + 1 ] = forms [ i + 1 ] . substring ( rp + 1 ) ;
}
}
sb. push ( forms [ i ] ) ;
form = sb. join ( '' ) . replace ( /\ufd3e/gm , '(' ) . replace ( /\ufd3f/gm , ')' ) ;
}
}
if ( form != null )
return form. replace ( /%%/gm , ' \u fffc' ) . replace ( /%/gm , arg ) . replace ( /\ufffc/gm , '%' ) ;
}
}
return arg ;
} ) ;
}
______________________