'제로'의 Android 복수형 처리


84

내 strings.xml에 다음과 같은 복수 자원이있는 경우 :

   <plurals name="item_shop">
        <item quantity="zero">No item</item>
        <item quantity="one">One item</item>
        <item quantity="other">%d items</item>
   </plurals>   

다음을 사용하여 사용자에게 결과를 보여줍니다.

textView.setText(getQuantityString(R.plurals.item_shop, quantity, quantity));

1 이상에서는 잘 작동하지만 수량이 0이면 "0 개 항목"이 표시됩니다. 문서에 표시된 것처럼 "0"값은 아랍어로만 지원됩니까? 아니면 내가 뭔가를 놓치고 있습니까?


21
이 문제는 여기 code.google.com/p/android/issues/detail?id=8287에서 보고됩니다 . 아직 수정되지 않음 : /
OcuS 2011

5
나는 그것이 버그라고 생각하지 않는다. 선택은 문법적 필요성에 따라 만들어 졌다는 점에 주목하라. 영어로 된 0 문자열은 수량이 0 인 경우에도 무시됩니다. 0은 문법적으로 2와 다르지 않거나 1을 제외한 다른 숫자 ( "zero books", "one book", "two books"등) on)
ByteMe

1
슬프게도 모든 언어는 영어와 동일하지
아르망

3
저는 이것이 문법을 제외하고 제가 이것을 사용하는 데 필요한 99 %의 시간 동안 누락 된 기능 이 필요하다는 점에서 버그라고 생각 합니다. 그렇습니다. 저는 이것이 Google이 결코 고치지 않을 버그라고 생각합니다. 따라서 해결 방법이 필요합니다. 알다시피, API는 소비자를 돕고 작업을 수행하기위한 것이지 현실 세계의 추상적 인 개념을 독점적으로 표현하는 것이 아닙니다. Zero가 기본적으로 지원된다면 두 그룹 (문법 정확성이 필요한 그룹과 그렇지 않은 그룹)은 다른 것을 사용하지 않고도 벗어날 수 있습니다.
Martin Marconcini

답변:


90

Android 리소스 국제화 방법은 매우 제한적입니다. 나는 표준을 사용하여 훨씬 더 나은 성공을 거두었습니다 java.text.MessageFormat.

기본적으로 다음과 같은 표준 문자열 리소스를 사용하기 만하면됩니다.

<resources>
    <string name="item_shop">{0,choice,0#No items|1#One item|1&lt;{0} items}</string>
</resources>

그런 다음 코드에서해야 할 일은 다음과 같습니다.

String fmt = getResources().getText(R.string.item_shop).toString();
textView.setText(MessageFormat.format(fmt, amount));

MessageFormat 에 대한 javadocs 에서 형식 문자열에 대해 자세히 읽을 수 있습니다.


7
좋은 해결 방법입니다. 내 애플리케이션을 번역하는 사람들이 내 파일에 어떤 종류의 엉망을
넣을지

1
"몇 가지"숫자 (2,3,4로 끝나지만 12,13,14로 끝나지 않는 숫자)에 대한 형식 문자열을 어떻게 구성합니까?
vokilam

4
와, 못 생겼 네요. 이와 같은 논리는 번역이 아닌 코드로 이루어져야합니다. 복수형은 숫자에 대한 언어 차이에만 도움이됩니다. "few"에 대한 권장 사항으로 이제 성공적으로 논리를 번역으로, 번역을 논리로 이동했습니다.
DennisK 2014 년

2
확실히 좋은 해결 방법은 아닙니다. no_items에 대한 문자열과 앞에 if 절을 추가하기 만하면됩니다. If (items.count == 0) {use the string} else {use the plural} 그러면 번역자들이 strings.xml 파일의 문제를 처리하도록합니다…
Martin

2
MartínMarconcini @ 당신은 올바른 ... 3 년 후 :-)
GreyBeardedGeek

47

에서 http://developer.android.com/guide/topics/resources/string-resource.html#Plurals :

선택은 문법적 필요성에 따라 이루어집니다. 영어로 된 0 문자열은 수량이 0 인 경우에도 무시됩니다. 0은 문법적으로 2와 다르지 않거나 1을 제외한 다른 숫자 ( "zero books", "one book", "two books"등) 의 위에). 양 2에만 적용될 수있는 것처럼 두 가지 소리가 들린다는 사실에 오해하지 마십시오. 언어는 2, 12, 102 (등)가 모두 서로 닮았지만 서로 다르게 취급 될 것을 요구할 수 있습니다. 수량. 번역가의 언어가 실제로 요구하는 차이점을 알기 위해 번역자에게 의뢰하십시오.

결론적으로 'zero'는 특정 언어에만 사용됩니다 ( 'two' 'few'등에도 동일 함). 다른 언어에는 특별한 활용이 없기 때문에 'zero'필드는 불필요한 것으로 간주되기 때문입니다.


4
"0은 2와 문법적으로 다르지 않기 때문에 수량이 0 인 경우에도 영어로 0을 나타내는 문자열은 무시됩니다."... "나는 과일이 없습니다"대 "나는 사과와 오렌지가 있습니다"는 어떻습니까?
Jeffrey Blattman 2012

4
단어 0 대 2에는 여러 가지 방법이 있습니다. 그러나 이러한 리소스 뒤에있는 아이디어는 숫자와 함께 사용하는 것입니다. 그래서 다음과 같습니다. 사과가 없습니다. 사과 1 개 있어요. 사과 2 개 있어요.
ByteMe 2011

4
유감 이네요. 언어 별 가정을 시도해서는 안됩니다. 내가 아는 모든 사람들이 복수형을 사용하는 것은 이것에 의해 혼란스러워졌습니다.
Jeffrey Blattman 2012

2
@ miracle2k : 메시지는 카테고리별로 번역되지 않으므로 한 언어로 된 카테고리 나 메시지는 다른 언어에 영향을주지 않습니다. 따라서 0 카운트에 대해서만 영어로 '제로'클래스 메시지가 있고 다른 언어가 '제로'클래스 메시지를 번역하지 않기 때문에 중요하지 않은 10,100 카운트에 대해 '제로'클래스를 사용하는 경우. 반면에 영어로 0 카운트에 대해 별도의 메시지 리소스를 만드는 경우 해당 사례가 이미 해당 언어의 원래 '0'클래스 메시지에 포함되어 있기 때문에 번역가를위한 워크 플로 문제를 생성하는 것입니다.
Basel Shishani

2
편의 기능으로 영어에서 "0"범주를 활성화하는 것은 사실이지만 "깨끗한"것은 아니며 나쁜 행동을 조장 할뿐입니다. 사용자가 "0"문자열에 항목을 추가하도록 권장하는 텍스트를 넣는 아이디어를 얻을 수 있습니다. 그러면 번역 할 수 없습니다. 엄밀히 말해서 OP의 예 ( "No items")는 번역자가 단어를 사용하여 0- 케이스를 구하기를 원할 수 있기 때문에 이미 그 문제를 보여줍니다. "% s 항목"을 "% s 항목"의 단일 버전으로 간주하고 "항목 없음"을 언어 적으로 완전히 다른 것으로 간주하면 워크 플로 문제가 아닙니다.
miracle2k

15

MessageFormat으로 전환하지 않고이 문제를 처리하는 데 사용하는 해결 방법은 다음과 같습니다.

먼저 "0"문자열을 자체 문자열 리소스로 추출합니다.

<string name="x_items_zero">No items.</string>
<plurals name="x_items">
    <!-- NOTE: This "zero" value is never accessed but is kept here to show the intended usage of the "zero" string -->
    <item quantity="zero">@string/x_items_zero</item>
    <item quantity="one">One item.</item>
    <item quantity="other">%d items.</item>
</plurals>

그런 다음 내 ResourcesUtil에 몇 가지 편리한 방법이 있습니다.

public static String getQuantityStringZero(Resources resources, int resId, int zeroResId, int quantity) {
    if (quantity == 0) {
        return resources.getString(zeroResId);
    } else {
        return resources.getQuantityString(resId, quantity, quantity);
    }
}

public static String getQuantityStringZero(Resources resources, int resId, int zeroResId, int quantity, Object... formatArgs) {
    if (quantity == 0) {
        return resources.getString(zeroResId);
    } else {
        return resources.getQuantityString(resId, quantity, formatArgs);
    }
}

이제 언제든지 호출하는 수량 0에 특정 문자열을 사용하고 싶습니다.

String pluralString = ResourcesUtil.getQuantityStringZero(
     getContext().getResources(),
     R.plural.x_items,
     R.string.x_items_zero,
     quantity
);

더 나은 것이 있었으면 좋겠지 만 최소한 문자열 리소스 XML을 읽을 수 있도록 유지하면서 작업을 완료합니다.


이것을 사용하면 "<item quantity ="zero ">"가 실제로 사용되지 않습니까?
안드로이드 개발자

4
올바른 '<item quantity = "zero">'는 사용되지 않습니다. 0에 대한 해당 값의 의도 된 용도를 명확히하는 데 도움이된다고 생각하기 때문에 여기에 있습니다.
Justin Fiedler

그렇게 생각. 번역자가 무슨 일이 일어나고 있는지 이해하는 데 도움이 될 수 있습니다.
안드로이드 개발자

13

Android는 CLDR 복수형 시스템을 사용하고 있으며 이는 작동 방식이 아닙니다 (변경 될 것으로 예상하지 마십시오).

시스템은 다음과 같습니다.

http://cldr.unicode.org/index/cldr-spec/plural-rules

요컨대, "1"은 숫자 1을 의미하지 않는다는 것을 이해하는 것이 중요합니다. 대신 이러한 키워드는 카테고리이고 각 카테고리에 속하는 특정 숫자 n은 CLDR 데이터베이스의 규칙에 의해 정의됩니다.

http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html

0 이외의 것에 대해 "0"을 사용하는 언어는없는 것처럼 보이지만 "1"에 0을 할당하는 언어가 있습니다. "2"에 2가 아닌 다른 숫자가 포함 된 경우가 많이 있습니다.

Android에서 의도 한대로 수행 할 수있는 경우 애플리케이션이 더 복잡한 복수 규칙을 사용하여 여러 언어로 제대로 번역되지 않을 수 있습니다.


5
여러 질문에 대한 상용구 / 언어 적 답변을 복사하여 붙여 넣을 때주의하세요. 이러한 질문은 커뮤니티에서 "스팸성"으로 표시되는 경향이 있습니다. 이 작업을 수행하는 경우 일반적으로 질문이 중복됨을 의미하므로 대신 다음과 같이 플래그를 지정하십시오. stackoverflow.com/questions/8473816
Kev

3

생각할 수있는 모든 시나리오를 처리하기 위해 Kotlin 확장 프로그램을 작성했습니다.

나는 zeroResId선택 사항으로, 때때로 우리는 "0 개 항목"이 아닌 "항목 없음"을 표시하여 0을 처리하려고합니다.

영어는 문법적으로 0을 복수로 취급합니다.

사용할 문자열의 선택은 전적으로 문법적 필요성에 따라 이루어집니다.

영어에서는 수량이 0 인 경우에도 0에 대한 문자열이 무시됩니다. 0은 문법적으로 2와 다르지 않거나 1을 제외한 다른 숫자 ( "zero books", "one book", "two books"등) 의 위에).

https://developer.android.com/guide/topics/resources/string-resource.html#Plurals

fun Context.getQuantityStringZero(
    quantity: Int, 
    pluralResId: Int, 
    zeroResId: Int? = null
): String {
    return if (zeroResId != null && quantity == 0) {
        resources.getString(zeroResId)
    } else {
        resources.getQuantityString(pluralResId, quantity, quantity)
    }
}

2

데이터 바인딩을 사용하는 경우 다음과 같이이 문제를 해결할 수 있습니다.

<TextView ... 
android:text="@{collection.size() > 0 ? @plurals/plural_str(collection.size(), collection.size()) : @string/zero_str}"/>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.