2009-07-21 13 views
10

あなたはブログソフトを作っているとし、エントリーのコメント数を表示したいとします。シングル/複数形を扱う最もエレガントな方法は?

[Entry title] 
[Content........] 
[ <?php print($numComments;) ?> Comments] 

になる可能性があります:

[Entry title] 
[Content........] 
5 Comments 

しかしエントリは1つだけのコメントがあった場合、私はラインではなく「コメント」よりも「コメント」を言いたいあなたは、このようにそれを行う可能性があります。そして、インラインでif/elseは醜く反復的です。

これに対処する最も良い方法は何ですか?

+4

+1、それが私に言ったので。それは賢明なことですが、私はそれだけであなたが得たアップボートがいくつあるのか知ることに興味があります。 :) – Dusty

+1

私は半誘惑私は数が1でない場合は0が同様に複数形を取得するよう機能は、Sを追加するだろう –

答えて

13

このようなことのためにngettext機能を使用してください。 を使用すると、英語の複数形や他の言語の を正しく扱うことができます。あなたはこのようにそれを使用します。複数ある場合は1つだけコメントして第二のフォーマット 文字列("%d Comments")がある場合

printf(ngettext("%d Comment", "%d Comments", $numComments), $numComments); 

ngettext関数は最初のフォーマット文字列("%d Comment")を返します。 printf関数は となり、数値を文字列に入れます。

は、これは多くの作業のように見えるかもしれませんが、それは非常に強力である:それは つ以上の複数形を持つ言語で を作品 - 彼らが存在し、実際に (!)。 PHPマニュアルには、 "window"という単語の例があります。 の言語では、 "1 okno"、 "2 okna"、 " 5 oken"になります。あなたはあなたに非常に感謝するでしょう、あなたの将来のユーザー遠くの国から を ngettextを、使用について、その結果としてある場合

:-)

編集:コメントで示唆したようには、単一の関数があります に上記の操作を行います。デフォルトでは

function pluralize($num, $singleWord, $pluralWord) { 
    return printf(ngettext($singleWord, $pluralWord, $num), $num); 
} 

を、xgettextは文句を言わない、この新しい機能を認識していますが、 --keywordフラグを追加することができます。あなたは

xgettext --keyword=pluralize:2,3 test.php 

messages.poファイルを使用して文字列を抽出することができます

echo ngettext("foo", "foos", 1); 
echo pluralize(2, "bar", "bars"); 

でファイルtest.phpを考えると、これらのようなエントリがあります。

#: test.php:7 
msgid "foo" 
msgid_plural "foos" 
msgstr[0] "" 
msgstr[1] "" 

#: test.php:8 
msgid "bar" 
msgid_plural "bars" 
msgstr[0] "" 
msgstr[1] "" 
翻訳者がそれぞれ複数形で入力されます

とメッセージカタログのヘッダに正しく 形成された「複数形を」ラインで、あなたは ことができるようになりますすべての言語をサポートします。

+0

これをprintfで常に使用することは繰り返しますが、おそらくprintfと%dを実行するラッパー関数を書くことができます。おそらくあなたはこの関数の本体を書いて答えを更新することができますか? 'function Up($ num、$ singleWord、$ pluralWord = '') –

+0

@ Upvote:良いアイデアをクリックしてください。私は3つの必須引数で関数を作成しました.xgettextが関数呼び出しを認識して正しく処理できるように、複数の文字列が必要です。 –

+0

それはスロバキア語です。 –

3

数値と単語をとり、両方を含む文字列を返す関数を作成します。数字が1より大きい場合は、「s」を追加します(または作成する辞書に相談してください)。

+1

をupvote人の影響を打ち消すためにちょうどdownvoteすることです。 –

+0

あなたはそのような関数を何と呼びますか? –

+0

Pluralizeは最もふさわしい名前のようです。 – Brandon

2

最もエレガントではありませんが、「Comment(s)」を出力するのが最も簡単です。さらに多くの事をヒト化するために時間がかかることはありませなぜ

[Entry title] 
[Content........] 
1 Comment(s) 
+0

簡単ですが、すべての状況でうまく動作しません –

+2

これは非常にエレガントではありません...私がそのような出力を見て、私はいつもコンピュータが余分なミリ秒を費やして "s"がそこにあるべきかどうかを知りませんでした.-) –

+0

+1 Haha。合意した – Dusty

4

....

switch ($numComments) 
{ 
    case 0: 
     echo "Be the first to write a comment"; 
     break; 
    case 1: 
     echo "Just one comment so far"; 
     break; 
    default: 
     echo "There are $numComments comments"; 

} 
+0

+1この方法は、ほとんどのローカライゼーションの問題を回避します。 – fishlips

+0

@fishlips:言語に3つ以上の複数形がある場合を除きます。以下で説明するように、ngettext関数はより一般的な解決策です。翻訳者は、複数のフォームをすべて ".po"ファイルに含め、実行時には正しいものを選択することができます。 –

3

それは誰もがそのまだ示唆していないことを私に驚き、しかし、私は通常、やっていることは条件演算子を使用することです。

string commentWord = numComments != 1 ? "Comments" : "Comment"; 

注:あなたが扱うことができるように、文字列はもちろん、ハード、すべてではなく、むしろそれは数の書式プレースホルダで保存されているいくつかのリソースリポジトリからロードされ、このようにコード化するべきではありません番号が最後(または中間に)表示されます言語:

// should load "{0} Comments" or "{0} Comment" if we run in an English locale 
string comments = string.Format(
     numComments != 1 ? GetResource("Comments") : GetResource("Comment"), 
     numComments); 
+4

これは国際化を行う正しい方法ではありません。英語以外の言語には、複数形の独自の規則があります。例えばリトアニア語には、「1つの公約」、「2つの公約」、「10の記念碑」という3つの異なる形式があります。 Cプログラムで一般的なGNU gettextフレームワークには、これに対する解決策(ngettext関数)があります。私はJava/C#/ PHPに精通していないので、標準的な正解が何であるかは言えません。 –

+0

@マリアス:その情報をありがとう。私はリトアニアのルールを知らなかった。私は多少の国際的なソフトウェアを作ったことがありますが(イベントは大規模なクライアントのためのUIテキストの翻訳ソフトウェアを作ったのですが)、そのような要求に遭遇したことはありません。とても興味深い!しかし、ここでは詳しく説明しませんが、ハード・コーディングだけでなく、リソース・リポジトリーからテキストを取り上げるという概念を導入したかったのです。 –

+0

@Fredrik:私は2つ以上の複数形を持つ言語について初めて聞いた時にも誇りを持っていました...私はデンマーク語で、2つの形式にしか使用しませんでした:-)幸いにも、ngettext関数はそれに対処できますこのページのどこかに答えてください。 –

0

Rails inflector moduleをチェックしてください。これは、この問題に対する優れた集中型の構成可能なソリューションを提供します。

2

は、C/C++では、次の操作を行うことができます。 PHPでも同様のことができるかもしれません。

printf("%d %s\n", numComments, numComments == 1 ? "Comment" : "Comments"); 

以下も動作しますが、あなたは、異なる実装で正しく処理され\b(バックスペース)の問題に遭遇することがあります。何も印刷しないように\0(ヌル文字)を使用して

printf("%d Comment%s\n", numComments, numComments == 1 ? " \b" : "s"); 

は、代わりに、私の実装ではスペースを印刷しました。ユーザー名については

関連する問題