사용자 메시지의 복수


106

사용자에게 표시하는 메시지를 생성 할 때 많은 시간, 메시지의 번호가 포함됩니다 뭔가를 내가 대해 고객에게 통보 할 것이다.

예를 들어 보겠습니다. 고객이 1 개 이상에서 여러 항목을 선택하고 삭제를 클릭했습니다. 이제 고객에게 확인 메시지를 전하고 싶은데, 그가 선택한 항목의 수를 언급하여 여러 항목을 선택하고 항목 중 하나만 삭제하고 싶을 때 삭제를 클릭하여 실수 할 가능성을 최소화하고 싶습니다. 그들.

한 가지 방법은 다음과 같은 일반 메시지를 만드는 것입니다.

int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " item(s). Are you sure you want to delete it/them?";

은 "문제는"여기의 경우 noofitemselected1, 우리는 쓰기에이 항목 대신 항목그들 .

내 정상적인 해결책은 다음과 같습니다.

int noofitemsselected = SomeFunction();
string message = "You have selected " + noofitemsselected + " " + (noofitemsselected==1?"item" : "items") + ". Are you sure you want to delete " + (noofitemsselected==1?"it" : "them") + "?";

코드 내부에 숫자에 대한 참조가 많고 실제 메시지를 읽기가 어려워지면 이것은 매우 길고 매우 끔찍해집니다.

그래서 제 질문은 간단합니다. 이와 같은 메시지를 생성하는 더 좋은 방법이 있습니까?

편집하다

메시지 상자 안에 메시지를 표시해야한다고 언급하고 메시지 상자 사용을 아예 피하는 방법에 대한 답변을 제공 한 경우에 많은 사람들이 매우 전화를 끊는 것을 보았습니다. .

그러나 복수화의 문제는 메시지 상자 외에 프로그램의 다른 위치에도 적용된다는 점을 기억하십시오. 예를 들어, 그리드에서 선택된 라인 수를 표시하는 그리드 옆의 레이블은 복수화와 관련하여 동일한 문제를 갖습니다.

따라서 이것은 기본적으로 프로그램에서 어떤 방식 으로든 출력되는 대부분의 텍스트에 적용되며 솔루션은 더 이상 텍스트를 출력하지 않도록 프로그램을 변경하는 것만 큼 간단하지 않습니다. :)


6
@ 0xA3 : 모든 언어가 "item (s)"처럼 쉽게 표현되는 복수형을 가지고 있는지 정말 모르겠습니다.
Jens

5
현지화에 대해서도 생각해야합니다. 이 문제는 훨씬 더 악화 될 수 있습니다.
Alex Brown

4
@Jens : 가능한 최소한 편리한 방법으로는 보통 그렇지 않습니다. 예를 들어 일부 언어는 성별에 따라 5 무한대와 2-4에 대해 다른 복수형을 갖습니다. "Natural Languages ​​: Localization Madness! 가까운 컴퓨터에서 곧 출시됩니다!"
Piskvor는

29
IMO, 프로그래머가 나쁜 복수보다 사용자에게 더 게으르게 보이게하는 것은 없습니다.
Greg

4
@ Øyvind : 편집에 +1. 여기에있는 많은 "답변자"는 옳은 해결책을 제공하기보다 귀하의 질문이 틀렸다는 것을 증명하는 데 더 많은 의지를 가지고있는 것 같습니다. 원할 경우 안티 솔루션.
mwolfe02 2010

답변:


53

아무리 작더라도이 앱을 다른 언어로 번역해야 할 가능성이 있다면 둘 다 잘못된 것입니다. 이를 수행하는 올바른 방법은 다음과 같습니다.

string message = ( noofitemsselected==1 ?
  "You have selected " + noofitemsselected + " item. Are you sure you want to delete it?":
  "You have selected " + noofitemsselected + " items. Are you sure you want to delete them?"
);

이것은 다른 언어가 복수를 다르게 처리하기 때문입니다. 말레이어와 같은 일부는 구문 상 복수형조차 없기 때문에 문자열은 일반적으로 동일합니다. 두 문자열을 분리하면 나중에 다른 언어를 더 쉽게 지원할 수 있습니다.

그렇지 않으면이 앱이 일반 대중이 사용하고 사용자 친화적이어야한다면 두 번째 방법이 바람직합니다. 죄송하지만이 작업을 수행하는 더 짧은 방법을 모르겠습니다.

이 앱이 회사 내부적으로 만 사용되도록 의도 된 경우 바로 가기를 수행하십시오 "item(s)". 진취적인 코드를 작성할 때 누구에게도 깊은 인상을 줄 필요는 없습니다. 그러나 이것은 프로그래머가 게으르다는 인상을 주므로 앱의 품질에 대한 의견을 낮추기 때문에 공개적으로 사용되는 앱에 대해이 작업을 수행하지 않는 것이 좋습니다. 저를 믿으세요,이 문제와 같은 작은 것들.


35
나는 전제에 동의하지만, 당신은 2도 이상의 복수도를 가진 언어를 무시하고 있습니다. (예를 들어 러시아어를 예로 들어 보겠습니다. 1, <5 또는> = 5인지에 따라 세 가지 다른 방식으로 말하고 심지어 정확히 무엇에 대해 말하는지에 따라 다릅니다). 기본적으로 삼항 연산자가 아니라 더 강력한 조건문이 필요하다고 말하는 것입니다.
crasic 2011

4
noofitemsselected이 예제에서 첫 번째 옵션에 대해 최적화 할 수도 있습니다. 당신이 알고 있기 때문에 1입니다.
기본값

16
히브리어는 1, 2, 3-10 및 11+에 대해 서로 다른 복수형을 가질 수 있습니다.
Joel Spolsky

3
@Joel, 히브리어는 다양한 복수형을 가질 수 있습니까? לא ידעתי (몰랐습니다)! 현대 히브리어 복수형 가서까지로 영어처럼 (비록 고대 히브리어는 듀얼 양식을했다.)
켄 블룸

3
영어에서 0은 복수 (0 개 항목, 2 개 항목)처럼 취급됩니다. 히브리어, 러시아어, 루마니아어에서 0은 어떻게 되나요? 범위를 식별하는 간단한 방법이 있습니까? 정보는 언어별로 결정되어야하므로 메시지 파일을 기반으로하는 모든 시스템은 메시지 집합에서 다양한 양의 복수를 처리해야합니다. 아야! 번역을 설정하는 것도 까다로울 수 있습니다. 언어마다 다른 수의 메시지가 필요합니다.
Jonathan Leffler

94

메시지없이 항목을 삭제하고 사용자에게 정말 좋은 실행 취소 기능을 제공함으로써이 모든 복잡한 복수를 피할 수 있습니다. 사용자는 아무것도 읽지 않습니다 . 당신은 좋은 취소 설비를 구축해야한다 어쨌든 프로그램의 일환으로.

포괄적 인 실행 취소 기능을 만들면 실제로 두 가지 이점이 있습니다. 첫 번째 이점은 사용자가 실수를 되돌리고 읽기를 최소화 할 수 있도록하여 사용자의 삶을 편하게합니다. 두 번째 이점은 앱이 실수뿐만 아니라 사소하지 않은 워크 플로의 반전을 허용하여 실제 생활을 반영한다는 것입니다.

한 번은 단일 대화 상자 나 확인 메시지를 사용하지 않고 앱을 작성했습니다. 심각한 생각이 필요했고 확인 유형 메시지를 사용하는 것보다 구현하기가 훨씬 더 어려웠습니다. 그러나 최종 결과는 최종 사용자에 따라 사용하기에 다소 좋았습니다.


12
어떤 이유로 나는 이것에 동의하고 찬성해야한다고 생각합니다.
Cody Gray

4
@ Øyvind, 이유는 다음과 같습니다. 사용자에게 확인을 요청하는 메시지는 특히 사용자가 대화 상자에 응답 할 때까지 모든 것을 중지 하는 모달 대화 상자의 형태로 제공되는 경우 사용자에게 비용이 많이 듭니다 . 이로 인해 많은 사용자가 아무 버튼이나 클릭하여 대화 상자를지나 가기 시작하는 지점까지 짜증이납니다 ( 다음, 다음, 다음을 클릭 한 설치 프로그램이 몇 명 입니까? ). 따라서 소프트 삭제를 수행하고 실행 취소 기능을 제공하면 더 안전하고 사용자 마찰이 훨씬 적습니다. Gmail은이 기술을 사용하여 큰 효과를냅니다.
Robert Harvey

5
논쟁의 여지가 있지만 어쨌든 삭제에 대한 확인 메시지가 아닌 경우 동일한 문제가 발생 하므로이 답변은 실제로 질문과 관련이 있습니다.
Jay

50
나는 그것을 읽지 않고 이것을 찬성했다. 나중에 언제든지 취소 할 수 있습니다
Steven A. Lowe

6
@Robert Harvey : 아마도 끔찍할 것입니다.하지만 몇 년 전 로터스가 맥용 로터스 노트 40,000 개를 출하했고 60,000 개가 반환되었다고 읽었습니다. 인터페이스가 너무 나빠서 해적판을 한 사람들도 그것을 돌려 보냈습니다.
Duncan

39

그냥 어때 :

string message = "Are you sure you want to delete " + noofitemsselected + " item(s)?"

이렇게하면 번호 동의 문제가 제거되고 사용자에게 더 짧고 정확한 오류 메시지가 추가로 표시됩니다. 우리 모두는 사용자가 어쨌든 오류 메시지를 읽지 않는다는 것을 알고 있습니다. 길이가 짧을수록 적어도 텍스트를 한 가능성이 높아 집니다.

또는 사용자가 오류 메시지를 읽지 않는다는 지식으로 무장하면 다른 방식으로 접근 할 수 있습니다. 확인 메시지를 모두 건너 뛰고 삭제 된 항목에 관계없이 Just Works라는 실행 취소 기능을 제공하십시오. 대부분의 사용자는 이미 원하는 작업이 아니라는 것을 알았을 때 작업을 실행 취소하는 데 익숙하며 다른 성가신 팝업을 처리하는 것보다이 동작이 더 자연 스럽습니다.


1
좋은 대답입니다. 그러나이 경우 고객은 이것이 최선의 접근 방식이라고 생각했기 때문에 많은 경우에 오류 메시지를 제공하도록 요청했습니다. 그러나 텍스트를 변경하면 최소한 문제를 최소화하고 덜 지저분하게 만들 수 있습니다.
Øyvind Bråthen 2010

@ Øyvind : 충분합니다. 고객을 따라야하기 때문에 제가 제안한 첫 번째 접근 방식을 취하거나 핸들러 기능이있는 Resources 파일을 사용합니다. 너무 쉽게 잊혀지기 때문에 대안을 지적 할 가치가 있다고 생각했습니다. 젠장, 첫 번째 답변을 제출할 때까지 생각조차하지 못했습니다.
Cody Gray

대안을 가장 환영합니다. 나는 그것을 한도 : 준 이유
Øyvind Bråthen

1
해결 불가능한 문제를 해결하지 않으려면 +1합니다. 그리고 Steve Krug의 법칙을 기억하십시오. 단어의 절반을 제거하십시오. 그런 다음 다시하십시오. 나는 사용 : "항목 {x} 개를 삭제 하시겠습니까?"
Serge Wautier 2011 년

20

Java가 수년 동안 가지고 있었던 것은 무엇입니까 : java.text.MessageFormat 및 ChoiceFormat? 자세한 내용은 http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html 을 참조하십시오.

MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
form.applyPattern(
   "There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.");

Object[] testArgs = {new Long(12373), "MyDisk"};

System.out.println(form.format(testArgs));

// output, with different testArgs
output: The disk "MyDisk" are no files.
output: The disk "MyDisk" is one file.
output: The disk "MyDisk" are 1,273 files.

귀하의 경우에는 좀 더 간단한 것을 원합니다.

MessageFormat form = new MessageFormat("Are you sure you want to delete {0,choice,1#one item,1<{0,number.integer} files}?");

이 접근 방식의 장점은 i18n 번들과 잘 작동하고 복수 또는 단수 단어 개념이없는 언어 (예 : 일본어)에 대해 적절하게 번역을 제공 할 수 있다는 것입니다.


1
이 접근법은 복수를 다루는 데는 잘 작동하지만 슬프게도 성별은 다루지 않습니다. 삭제할 수있는 사물의 종류마다 다른 문자열이 필요합니다.
Mr. Shiny and New 安 宇

명사를 알고 있다면 적절한 형용사와 함께 작동하도록 문장을 만들 수 있습니다. 그러나 예, 고전 그리스어를 공부 한 후 남성, 여성 또는 중성 명사 (형용사는 수정하는 명사의 형태를 취함)를 기반으로 한 단어의 다른 형태를 가지며, 형태는 문장의 기능에 따라 다릅니다 ( 주제, 대상 등). 우리는 항상 하나의 솔루션이 작동하고 다른 솔루션이 작동하지 않는 경우를 생각 해낼 수 있습니다. 이것이 자바 사람들이 문제를 해결하려고 시도한 방식입니다. 메시지 형식을 구성하는 방법에는 여전히주의해야합니다.
Berin Loritsch 2010

Java 솔루션에 항상 두 개의 정수를 제공 할 수 있으며 두 번째는 성별을 나타냅니다. (그러나 실제로는 메시지에 다른 개체를 맞추는 사용 사례가 메시지에 동일한 개체의 다른 수를 맞추는 것보다 덜 빈번하기 때문에 성별 동의는 일반적으로 덜 우려됩니다.)
Ken Bloom

12

메시지를 하드 코딩하지 않고 별도의 리소스 파일에 두 개의 메시지를 제공합니다. 처럼

string DELETE_SINGLE = "You have selected {0} item. Are you sure you want to delete it?";
string DELETE_MULTI = "You have selected {0} items. Are you sure you want to delete them?";

그런 다음 String.Format에 다음과 같이 공급합니다.

if(noofitemsselected == 1)
    messageTemplate = MessageResources.DELETE_SINGLE;
else
    messageTemplate = MessageResources.DELETE_MULTI;

string message = String.Format(messageTemplate, noofitemsselected)

이 접근 방식은 현지화 및 유지 관리가 더 쉽다고 생각합니다. 모든 UI 메시지는 단일 위치에 있습니다.


+1,이 접근 방식이 마음에 듭니다. 하지만 리소스 이름에 해당하는 항목을 추적해야합니다.
기본적으로

11

메시지를 다르게 표현하여 문제를 완전히 회피 할 수 있습니다.

string message = "The number of selected items is " + noofitemsselected + ". Are you sure you want to delete everything in this selection?";

10

내가 제안하고 싶은 첫 번째 것은 : use string.Format. 이렇게하면 다음과 같이 할 수 있습니다.

int numOfItems = GetNumOfItems();
string msgTemplate;
msgTemplate = numOfItems == 1 ? "You selected only {0} item." : "Wow, you selected {0} items!";
string msg = string.Format(msgTemplate, numOfItems);

또한 WPF 앱에서 리소스 문자열이 파이프로 구분되어 단수 및 복수 메시지 (또는 0 / 단일 / 다수 메시지)를 포함하는 시스템을 보았습니다. 그런 다음 사용자 지정 변환기를 사용하여이 리소스를 구문 분석하고 관련 (서식이 지정된) 문자열을 사용할 수 있으므로 Xaml은 다음과 같습니다.

<TextBlock Text="{Binding numOfItems, Converter={StaticResource c:NumericMessageFormatter}, ConverterParameter={StaticResource s:SuitableMessageTemplate}}" />

7

영어의 경우 위에 많은 답변이 있습니다. 다른 언어의 경우 복수형은 명사의 성별과 어미 단어에 따라 달라지기 때문에 더 어렵습니다. 프랑스어로 된 몇 가지 예 :

일반 남성 :

Vous avez choisi 1 compte. Voulez-vous vraiment le supprimer.
Vous avez choisi 2 comptes. Voulez-vous vraiment les supprimer.

일반 여성

Vous avez choisi 1 table. Voulez-vous vraiment la supprimer.
Vous avez choisi 2 tables. Voulez-vous vraiment les supprimer.

불규칙한 남성 ( 's'로 끝남)

Vous avez choisi 1 pays. Voulez-vous vraiment le supprimer.
Vous avez choisi 2 pays. Voulez-vous vraiment les supprimer?

동일한 문제가 대부분의 라틴어에 존재하며 독일어 또는 러시아어에서 3 개의 성별 (남성 성, 여성 성 및 중성)이있는 경우 더욱 악화됩니다.

당신의 목표가 영어 이상의 것을 다루는 것이라면주의가 필요합니다.


적어도 제 경우에는 이것은 실제로 문제가 아닙니다. 숫자를 삽입하려는 각 텍스트에 대해 문자열을 생성 할 때 명사가 무엇인지 알게됩니다. 그러나 좀 더 일반적인 해결책을 만들기 위해서는 "모든"언어에서 작동하도록 만드는 것이 불가능하지는 않지만 매우 어려울 수 있다는 점에 동의합니다.
Øyvind Bråthen 2010

1
또는 숫자에 따라 사용되는 명사의 복수형이 다른 폴란드어를 사용하세요! : /
UpTheCreek

5

적절하게 현지화 할 수있는 복수화 된 메시지를 가질 수 있으려면 먼저 번호와 메시지 사이에 간접적 인 레이어를 만드는 것이 현명하다고 생각합니다.

예를 들어 어떤 종류의 상수를 사용하여 표시 할 메시지를 지정합니다. 구현 세부 정보를 숨기는 일부 기능을 사용하여 메시지를 가져옵니다.

get_message(DELETE_WARNING, quantity)

다음으로 가능한 메시지와 변형을 보유하는 사전을 만들고 변형이 언제 사용되어야하는지 알 수 있도록합니다.

DELETE_WARNING = {
   1: 'Are you sure you want to delete %s item',
   >1: 'Are you sure you want to delete %s items'
   >5: 'My language has special plural above five, do you wish to delete it?'
}

이제에 해당하는 키를 찾고 해당 메시지로 quantity의 값을 보간 할 수 quantity있습니다.

이 지나치게 단순하고 순진한 예이지만,이 작업을 수행하는 다른 정상적인 방법은 없으며 L10N 및 I18N에 대한 좋은 지원을 제공 할 수 없습니다.


5

아래 함수를 VBA에서 C #으로 변환해야하지만 사용법은 다음과 같이 변경됩니다.

int noofitemsselected = SomeFunction();
string message = Pluralize("You have selected # item[s]. Are you sure you want to delete [it/them]?", noofitemsselected);

나는 MS Access에서 사용하는 VBA 기능을 사용하여 당신이 말하는 것을 정확하게 수행합니다. 나는 VBA를 게시하기 위해 해킹 당할 것이라는 것을 알고 있지만 어쨌든 여기에 있습니다. 알고리즘은 주석에서 분명해야합니다.

'---------------------------------------------------------------------------------------'
' Procedure : Pluralize'
' Purpose   : Formats an English phrase to make verbs agree in number.'
' Usage     : Msg = "There [is/are] # record[s].  [It/They] consist[s/] of # part[y/ies] each."'
'             Pluralize(Msg, 1) --> "There is 1 record.  It consists of 1 party each."'
'             Pluralize(Msg, 6) --> "There are 6 records.  They consist of 6 parties each."'
'---------------------------------------------------------------------------------------'
''
Function Pluralize(Text As String, Num As Variant, Optional NumToken As String = "#")
Const OpeningBracket = "\["
Const ClosingBracket = "\]"
Const DividingSlash = "/"
Const CharGroup = "([^\]]*)"  'Group of 0 or more characters not equal to closing bracket'
Dim IsPlural As Boolean, Msg As String, Pattern As String

    On Error GoTo Err_Pluralize

    If IsNumeric(Num) Then
        IsPlural = (Num <> 1)
    End If

    Msg = Text

    'Replace the number token with the actual number'
    Msg = Replace(Msg, NumToken, Num)

    'Replace [y/ies] style references'
    Pattern = OpeningBracket & CharGroup & DividingSlash & CharGroup & ClosingBracket
    Msg = RegExReplace(Pattern, Msg, "$" & IIf(IsPlural, 2, 1))

    'Replace [s] style references'
    Pattern = OpeningBracket & CharGroup & ClosingBracket
    Msg = RegExReplace(Pattern, Msg, IIf(IsPlural, "$1", ""))

    'Return the modified message'    
    Pluralize = Msg
End Function

Function RegExReplace(SearchPattern As String, _
                      TextToSearch As String, _
                      ReplacePattern As String) As String
Dim RE As Object

    Set RE = CreateObject("vbscript.regexp")
    With RE
        .MultiLine = False
        .Global = True
        .IgnoreCase = False
        .Pattern = SearchPattern
    End With

    RegExReplace = RE.Replace(TextToSearch, ReplacePattern)
End Function

위의 코드 주석에서 사용법이 약간 잘렸으므로 여기서 반복하겠습니다.

Msg = "There [is/are] # record[s]. [It/They] consist[s/] of # part[y/ies] each."

Pluralize(Msg, 1) --> "There is 1 record.  It consists of 1 party each."
Pluralize(Msg, 6) --> "There are 6 records.  They consist of 6 parties each."

예,이 솔루션은 영어가 아닌 언어를 무시합니다. 그것이 중요한지 여부는 요구 사항에 따라 다릅니다.


4

복수형을 자동으로 생성 할 수 있습니다. 복수 생성기 .

복수 생성 규칙은 wikipedia를 참조하십시오.

string msg = "Do you want to delete " + numItems + GetPlural(" item", numItems) + "?";

응용 프로그램이 국제화되지 않은 경우이 방법을 사용하는 것이 좋습니다. Puralising은 더 세련된 응용 프로그램을 만듭니다.
cspolton 2010

1
이것을 국제화하기가 정말 어렵고 영어로 실패하는 경우가 많습니다. 예 : "You have orders + numMice + GetPlural ("mouse ", numMice)"
James Anderson

@James Anderson : 문법적으로 가장 좋은 예는 아닙니다. ;-) GetPural 메서드를 사용하는 것이 허용되는 유일한 방법이라고 생각하는 함정에 빠지지 마십시오 .
cspolton 2010

몇 가지 더 많은 코너 케이스를 처리하기 위해 몇 가지 더 많은 기능과 결합되어 있지만 이것이 짧지는 않지만 매우 좋은 솔루션이라고 생각합니다.
lalli

4

좀 더 일반적인 방법은 어떻습니까? 두 번째 문장에서 복수형을 사용하지 마십시오.

삭제할 선택된 항목 수 : 선택된 항목 없음.
확실합니까?

이렇게하면 정말 찾기 쉬운 줄 끝에 숫자가 표시된다는 것을 알았습니다. 이 솔루션은 모든 언어에서 동일한 논리로 작동합니다.


"삭제할 항목 선택 :"이 제대로 들리지 않고 문장이 이름 목록을 나타내지 만 숫자가 인쇄됩니다. "삭제할 항목 수 :"로 변경해도 여전히 "항목"이 어색합니다.
lalli

@lalli : 예, 문구가 완벽하지 않으며 제공된 솔루션 중 어느 것도 완벽하게 들리지 않습니다. 나는 그것을 레이블과 가치와 같은 형태로 넣으라고 제안하고 있습니다. 당신은 추가하는 것에 대해 옳습니다 Number(나는 아기를 잠들게하면서 대답했습니다).
Danosaure 2010

4

내 일반적인 접근 방식은 다음과 같이 "단일 / 복수 함수"를 작성하는 것입니다.

public static string noun(int n, string single, string plural)
{
  if (n==1)
    return single;
  else
    return plural;
}

그런 다음 메시지 본문에서이 함수를 호출합니다.

string message="Congratulations! You have won "+n+" "+noun(n, "foobar", "foobars")+"!";

이것은 훨씬 더 좋지는 않지만 적어도 (a) 결정을 함수에 넣고 코드를 약간 정리하고 (b) 불규칙한 복수형을 처리 할 수있을만큼 유연합니다. 즉 명사 (n, "child", "children") 등을 쉽게 말할 수 있습니다.

물론 이것은 영어에서만 작동하지만 개념은 더 복잡한 어미를 가진 언어로 쉽게 확장 할 수 있습니다.

쉬운 경우 마지막 매개 변수를 선택 사항으로 만들 수 있습니다.

public static string noun(int n, string single, string plural=null)
{
  if (n==1)
    return single;
  else if (plural==null)
    return single+"s";
  else
    return plural;
}

1
명사를 복수화하기 위해 s 를 추가하는 기본 작업의 경우 기본값을 사용하여 코드를 "정리 화"하는 마지막 부분이 마음 에 듭니다.
Øyvind Bråthen 2010

4

국제화

국제화 지원을 원한다고 가정합니다.이 경우 다른 언어는 복수형에 대해 서로 다른 패턴을 가지고 있습니다 (예 : 2 개에 대한 특수 복수형 또는 폴란드어와 같은 더 복잡한 언어). 문자열에 간단한 패턴을 적용하는 데 의존 할 수 없습니다. 그것을 해결하기 위해.

GNU Gettext의 ngettext기능을 사용하고 소스 코드에 두 개의 영어 메시지를 제공 할 수 있습니다 . Gettext는 다른 언어로 번역 될 때 다른 (잠재적으로 더 많은) 메시지에서 선택할 수있는 인프라를 제공합니다. GNU gettext의 복수 지원에 대한 전체 설명은 http://www.gnu.org/software/hello/manual/gettext/Plural-forms.html 을 참조 하십시오 .

GNU Gettext는 LGPL에 속합니다. Gettext의 C # 포트에 ngettext이름이 지정 GettextResourceManager.GetPluralString됩니다.

(현지화 지원이 필요하지 않고 Gettext를 즉시 사용하고 싶지 않다면 영어로이 작업을 수행하는 고유 한 함수를 작성하고 두 개의 전체 메시지 를 전달 합니다. 나중에 l10n이 필요한 경우 이렇게 할 수 있습니다. 단일 함수를 다시 작성하여 추가하십시오.)


3

같은 함수를 작성하는 방법

string GetOutputMessage(int count, string oneItemMsg, string multiItemMsg)
{
 return string.Format("{0} {1}", count, count > 1 ? multiItemMsg : oneItemMsg);
}

.. 필요할 때마다 사용 하시겠습니까?

string message = "You have selected " + GetOutputMessage(noofitemsselected,"item","items") + ". Are you sure you want to delete it/them?";

3
당신은 그것에 대해 생각하지 않았습니까? 당신은 곱셈을 분류하는 기능이 있거나 문장을 위해 말하지 않은 다음 마지막에 "it / them"을 넣습니다 lol
Barkermn01

이 함수에 전체 문장에 대한 두 개의 메시지를 전달해야합니다.
Ken Bloom

단지 예일뿐입니다. 전체 문장을 보내는 변형이 더 정확하다는 것을 알고 있습니다.
Pavel Morshenyuk 2010

3

첫 번째 문제는 Pluralize를 의미 합니다 . Inflector 를 사용할 수 있습니다 .

그리고 두 번째로 ToPronounString과 같은 이름을 가진 문자열 표현 확장을 사용할 수 있습니다.


3

어제 우리 팀원이 저에게 똑같은 질문을 던졌습니다.

여기 StackOverflow에 다시 올라온 이후로 나는 우주가 괜찮은 솔루션을 생산하는 데 bash가 있다고 말하고 있다고 생각했습니다.

나는 신속하게 무언가를 모았고 결코 완벽하지는 않지만 유용하거나 토론 / 개발을 촉발시킬 수 있습니다.

이 코드는 3 개의 메시지가있을 수 있다는 생각을 기반으로합니다. 다음 구조를 따르는 0 개 항목에 대해 하나, 하나의 항목에 대해 하나 및 둘 이상의 항목에 대해 하나 :

singlePropertyName
singlePropertyName_Zero
singlePropertyName_Plural

리소스 클래스를 모방하기 위해 테스트 할 내부 클래스를 만들었습니다. 아직 실제 리소스 파일을 사용하여 테스트하지 않았으므로 아직 전체 결과를 보지 못했습니다.

여기에 코드가 있습니다 (현재 저는 세 번째 매개 변수를 단순히 Type으로 지정할 수 있고 두 번째 매개 변수도 문자열이라는 것을 알고있는 몇 가지 제네릭을 포함했습니다.이 두 매개 변수를 더 나은 것으로 결합하는 방법이 있다고 생각합니다. 여유 시간이있을 때 다시 돌아 올게요.

    public static string GetMessage<T>(int count, string resourceSingularName, T resourceType) where T : Type
{
    var resourcePluralName = resourceSingularName + "_Plural";
    var resourceZeroName = resourceSingularName + "_Zero";
    string resource = string.Empty;
    if(count == 0)
    {
        resource = resourceZeroName;
    }
    else{
        resource = (count <= 1)? resourceSingularName : resourcePluralName;
    }
    var x = resourceType.GetProperty(resource).GetValue(Activator.CreateInstance(resourceType),null);

    return x.ToString();
}

테스트 리소스 클래스 :

internal class TestMessenger
{
    public string Tester{get{
    return "Hello World of one";}}
    public string Tester_Zero{get{
    return "Hello no world";}}
    public string Tester_Plural{get{
    return "Hello Worlds";}}
}

내 빠른 실행 방법

void Main()
{
    var message = GetMessage(56, "Tester",typeof(TestMessenger));
    message.Dump();
}

이 작업을 실제로 완료하려면 메시지를 추가하여 singlePropertyName_All더욱 분명하게 만들어야합니다.
Danosaure 2010

2

내 관점에서 첫 번째 솔루션이 가장 적합한 솔루션입니다. 즉, 여러 언어를 지원하는 응용 프로그램이 필요한 경우 두 번째 옵션이 어려울 수 있습니다. 첫 번째 접근 방식을 사용하면 많은 노력없이 텍스트를 쉽게 현지화 할 수 있습니다.


2

'선택한 항목을 삭제 하시겠습니까?'와 같은보다 일반적인 메시지로 이동할 수 있습니다.


3
이것은 확실히 효과가 있지만 삭제 될 항목의 수를 한 눈에 보여주는 질문자의 아이디어가 좋은 것이라고 생각합니다. 한 번 이상 데스크탑에서 파일을 삭제하려고했지만 실수로 그 파일보다 두 개 이상을 삭제했습니다.
Cody Gray

2

나는 당신이 얼마나 좋은 메시지를 갖고 싶은지에 달려 있습니다. 가장 쉬운 것부터 가장 어려운 것까지 :

  1. 복수형을 피하기 위해 오류 메시지를 다시 작성하십시오. 사용자에게는 좋지 않지만 더 빠릅니다.

  2. 보다 일반적인 언어를 사용하되 여전히 숫자를 포함합니다.

  3. Rails에서 "복수화"및 인플 렉터 시스템을 사용 pluralize(5,'bunch')하면 5 bunches. Rails는 이에 대한 좋은 패턴을 가지고 있습니다.

  4. 국제화를 위해서는 Java가 제공하는 것을 살펴 봐야합니다. 이는 2 개 또는 3 개의 항목이있는 서로 다른 형태의 형용사를 포함하는 다양한 언어를 지원합니다. "s"솔루션은 영어 중심입니다.

사용하는 옵션은 제품 목표에 따라 다릅니다. -ndp


2

사용자가 실제로 이해할 수있는 메시지를 제시하고 싶은 이유는 무엇입니까? 40 년의 프로그래밍 역사에 위배됩니다. Nooooo, 우리는 좋은 일이 있습니다. 이해할 수있는 메시지로 그것을 망치지 마십시오 .


(j / k)


+1 : 여기서도 유머를 보게되어 반갑습니다. 그러나 당신이 농담하더라도 나는 당신의 근본적인 요점을 이해합니다. 수년 동안 만들어진 많은 프로그램에는 매우 나쁜 메시지가 있습니다. 일반적으로 일반 사용자가 어쨌든 이해할 수 있도록 기술적 인 방법을 사용하기 때문입니다.
Øyvind Bråthen 2010

좋은 지적. 저는 "사용자 입력에 대한 오류 494-B"와 같은 메시지를받을 때 항상 그것을 좋아합니다. 그것은 삶을 훨씬 더 흥미롭게 만드는 잘못된 것에 대한 약간의 미스터리를 추가합니다. 최근에 "비밀번호가 보안 요구 사항을 충족하지 않습니다"라는 비밀번호를 생성하는 중에 오류가 발생했습니다. 내가 충족하지 못한 요구 사항에 대한 힌트는 없습니다. 내 비밀번호에는 대문자와 소문자가 모두 포함되어 있으며 여러 자리가 포함되어 있습니다. 시셜 캐릭터를 추가해 보았습니다. 아직도 아니야. 캐릭터를 삭제했을 때 드디어 지나갔습니다. 같은 캐릭터를 두 번 연속으로 가질 수 없다는 규칙이 있다고 생각합니다.
Jay 2014

2

월드 오브 워크래프트에서하는 것처럼하세요 :

BILLING_NAG_WARNING = "Your play time expires in %d |4minute:minutes;";

0

조금 더 짧아집니다.

string message = "Are you sure you want to delete " + noofitemsselected + " item" + (noofitemsselected>1 ? "s" : "") + "?";

0

내가 언급하지 않은 한 가지 접근 방식은 대체 / 선택 태그를 사용하는 것입니다 (예 : "You are about to squash {0} [? i ({0} = 1) : / cactus / cacti /]"). (즉, 정수로 간주되는 인수 0이 1과 같은지 여부에 따라 대체를 지정하는 형식과 같은식이 있습니다.) .net 이전에 사용 된 태그를 본 적이 있습니다. .net의 표준이 아니며 형식을 지정하는 가장 좋은 방법도 모릅니다.


0

여기에서 제안하는 모든 것은 복수화 (복수화, 성별 등의 1 단계 이상에 대해 걱정)를 수행하거나 전혀 사용하지 않고 멋진 실행 취소를 제공하는 것입니다.

나는 비언어적 방법으로 가서 시각적 대기열을 사용합니다. 예를 들어 손가락을 닦아서 항목을 선택하는 Iphone 앱을 상상해보십시오. 마스터 삭제 버튼을 사용하여 삭제하기 전에 선택한 항목을 "흔들고"V (확인) 또는 X (취소) 버튼이있는 물음표 상자를 표시합니다.

또는 Kinekt / Move / Wii의 3D 세계에서 파일을 선택하고 손을 삭제 버튼으로 이동 한 다음 확인을 위해 손을 머리 위로 이동하라는 지시를받는 것을 상상해보십시오 (앞에서 언급 한 것과 동일한 시각적 기호를 사용합니다. 3 개의 파일을 삭제하라는 메시지가 표시되면 반투명 빨간색 X가있는 3 개의 파일이 표시되고 확인 작업을 수행하라는 메시지가 표시됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.