简体   繁体   English

用于浮点值的 Android 复数

[英]Android Plurals for float values

I would like to use plurals for my Android project.我想为我的 Android 项目使用复数形式。 However, the values I provide can be float values.但是,我提供的值可以是浮点值。

So for instance, when setting 1.5 stars, I want this to understand, it's not 1 star but 1.5 star s .因此,例如,当设置 1.5 星时,我想让它明白,它不是 1 星而是 1.5 星s

<plurals name="stars">
  <item quantity="one">%d star</item>
  <item quantity="other">%d stars</item>
</plurals>

However, the Android system seems to use integer values (%d) only.但是,Android 系统似乎只使用整数值 (%d)。

The method looks like this:该方法如下所示:

String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)

where quantity is defined as Int .其中数量定义为Int

Is there any solution for this?有什么解决办法吗?

First I have to say: very interesting question. 首先我要说:非常有趣的问题。

Secondly this is the solution: Use %s instead of %d for your placeholder. 其次,这是解决方案:使用%s而不是%d作为占位符。

<plurals name="stars">
    <item quantity="one">%s star</item>
    <item quantity="other">%s stars</item>
</plurals>

Then you have to use Math.ceil() on your quantity. 然后你必须在数量上使用Math.ceil() So 1.1f for example would become 2 and therefore your text would turn from star to star s . 因此1.1f例如将成为2 ,因此你的文字会从明星变成明星

I have written this solution in Kotlin and Java. 我在Kotlin和Java中编写了这个解决方案。


For Kotlin I wrote an extension function which looks like this: 对于Kotlin,我写了一个扩展函数,如下所示:

    fun Resources.getQuantityString(@PluralsRes pluralResId: Int, pluralValue: Float) =
       this.getQuantityString(R.plurals.stars, Math.ceil(pluralValue.toDouble()).toInt(), pluralValue)

which would be called like this: tvText.text = resources.getQuantityString(R.plurals.stars, 1.1f) 这将被称为: tvText.text = resources.getQuantityString(R.plurals.stars, 1.1f)


For Java my solution looks like this: 对于Java,我的解决方案如下所示:

import android.content.res.Resources;
import android.support.annotation.PluralsRes;

public class PluralResource {
    public static String get(Resources resources, @PluralsRes int pluralResId, float pluralValue) {
        return resources.getQuantityString(pluralResId, (int) Math.ceil(pluralValue), pluralValue);
    }
}

which is called like this: 这被称为:

tvText.text = PluralResource.get(resources, R.plurals.stars, 1.1f)

Simply do this: 只需这样做:

getQuantityString(R.plurals.stars, quantity > 1f ? 2 : 1, quantity):

And replace the %d in your strings with %f. 并用%f替换字符串中的%d。

Don't use plurals for fractional numbers.不要对小数使用复数形式。 Just stick with basic string resources and use a placeholder:只需坚持基本的字符串资源并使用占位符:

<string name="fractional_stars">%1$s stars</string>

getString(R.string.fractional_stars, 0.5F.toString())

or要么

<string name="fractional_stars">% stars</string>

getString(R.string.half_a_star).replace("%", 0.5F.toString())

After doing further research, it appears there is no good solution for this . 经过进一步研究后,似乎没有好的解决方案

As also seen in the other answers, they always require a lot of "manual processing" to it requiring no different workflow than creating separate string resources. 正如在其他答案中看到的那样,它们总是需要大量的“手动处理”,而不需要创建单独的字符串资源。

The general suggestion seems to be rounding / processing the float values manually (eg checking whether the float value matches 1.0) and then using apropriate Int values for the plurals call. 一般建议似乎是手动舍入/处理浮点值(例如,检查浮点值是否匹配1.0),然后对复数调用使用适当的Int值。

But aside from not really using plurals then this comes with the problem of other languages (eg I have no clue if 1.5 stars would also be plural in another language as it is in English) and thus these rounding options may not apply universally. 但除了没有真正使用复数之外,这还伴随着其他语言的问题(例如,我不知道1.5星也会在另一种语言中复数,因为它是英语)因此这些舍入选项可能不适用于普遍。

So the answer is: there seems to be no perfect solution (meaning solved "automatically" by the Android system). 所以答案是:似乎没有完美的解决方案(意思是由Android系统“自动”解决)。

What I actually do therefore is to simply pick exceptions and use different Strings there. 因此我实际上只是选择异常并在那里使用不同的字符串。 So the (pseudo code) way of doing currently looks like 所以(伪代码)的做法目前看起来像

// optionally wrap different languages around
// if language == English

   when (amountStars) {
    is 1.0 -> getString(R.string.stars_singular, 1) 
    ... ->
    else -> getString(R.string.stars_plural, amountStars)
   }
// if language == Chinese ...

where additional cases have to be "hard coded". 其他案件必须“硬编码”。 So for example you have to decide whether 0 means 因此,例如,你必须决定0是否意味着

" 0 star s " (plural string) or 0 star s ”(复数字符串)或

" no star " (singular string) 没有明星 ”(单数字符串)

But there seems no real benefit of using plurals over separate string resources with common placeholders. 但是,对于使用共同占位符的单独字符串资源,使用复数似乎没有任何实际好处。 On the other hand this (at last for me) gives more flexibility for formatting options. 另一方面,这(对我而言)为格式化选项提供了更大的灵活性。 For example, one may create a text like "1 star and a half" where it becomes singular again (even though numerically we would write 1.5 stars). 例如,人们可以创建一个像“1星半”的文本,它再次成为单数(尽管在数字上我们会写1.5星)。

getQuantityString takes a quantity of type Int and Object... formatArgs If you round the quantity to Int you would make sure that any value in 1.0 -> 1.99 is a single item and other than that is a plural getQuantityString 接受类型为 Int 和 Object 的数量... formatArgs 如果将数量四舍五入为 Int,您将确保 1.0 -> 1.99 中的任何值都是单个项目,除此之外是复数

 resources.getQuantityString(
            R.plurals.products_left_in_stock_message_plural,
            leftInStock.toInt(), leftInStock.toString()
        )

So you only round it the quantity but pass the actually value as an argument所以你只将它四舍五入,但将实际值作为参数传递

<plurals name="products_left_in_stock_message_plural">
    <item quantity="one">Only one item is available from this product</item>
    <item quantity="other">There are only %s item is available from this product</item>
</plurals>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM