C#実装、Javascript:文字列のローカライズに便利なフォーマット関数

Habrauser afanのトピックIdea:文字列の便利なローカライズのためのフォーマット関数は、興味深い概念を示唆しました。 実際にエンジンで使用することにしました。



そしてそう



もちろん、正直な人として、私はこのトピックに関するすべてのコメントを読み、この式のリストを見つけました。 言語のサポートを追加するには、リストから式をコピーするだけです。



その後、既製のソリューションを探すことにしました。 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 ;

} ) ;

}










______________________

テキストは、©SoftCoder.ruのHabr Editorで作成されます。



All Articles