Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for plurals #2

Closed
Turbo87 opened this issue Jan 23, 2014 · 17 comments
Closed

Support for plurals #2

Turbo87 opened this issue Jan 23, 2014 · 17 comments

Comments

@Turbo87
Copy link

Turbo87 commented Jan 23, 2014

How do you handle "1 Beer" vs "3 Beers" with this library? Is there any special code for that or is something like that planned?

@loganj
Copy link
Collaborator

loganj commented Jan 23, 2014

We use separate string resources for those cases, and have done since before Phrase. "Beer" or "Beers" would be baked into the resource string, not substituted in by Phrase. This makes life easy for translators and only adds a simple conditional or switch statement for developers.

Generally we have at most four cases: none, one, some, and all.

<string id="beer_none">No Beers</string>
<string id="beer_one">1 Beer</string>
<string id="beer_some">{count} Beers</string>
<string id="beer_all">All Beers</string>

It's rare to have to do this at all, and extremely rare to have all four cases. Grepping our strings.xml, which contains nearly 800 string resources, shows maybe ten cases where we had to have multiple versions of a string to support different cardinalities.

@Turbo87
Copy link
Author

Turbo87 commented Jan 23, 2014

I see. The reason I'm asking is because some (actually many) languages have more difficult rules for pluralization (see http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html) and those rules unfortunately can't be expressed with a simple x == 1 ? "Beer" : "Beers".

@loganj
Copy link
Collaborator

loganj commented Jan 23, 2014

Right, that's exactly why we bake the nouns into the template and just have our translators handle it. Developers add the English default string and our translators do the rest. We use Shuttle to manage the process.

We avoid trying to generate natural-language strings that embed improper nouns from user input, in part so that we don't have to attempt to pluralize those nouns.

@Turbo87
Copy link
Author

Turbo87 commented Jan 23, 2014

I implemented an easy possible solutions in #3. Let me know what you think.

@dlew
Copy link
Contributor

dlew commented Mar 17, 2014

I'd like to reopen plurals for discussion.

If base your strings on English you might not cover all the pluralization cases needed by translators.

In English there is no distinction between "1 beer" and "2 beers", but apparently there is a difference in Welsh. There's a bunch of examples of of this problem in the Android docs: http://developer.android.com/guide/topics/resources/string-resource.html#Plurals

@loganj
Copy link
Collaborator

loganj commented Mar 17, 2014

Thanks, @dlew. The discussion isn't closed, and @Turbo87's PR #3 is still open. At this point I'm sold on supporting pluralization. We just need to get the API right. There are some other breaking API changes I'd like to make as well, and I think it makes sense to bundle them into a single release. Just haven't had time to do it yet.

@pforhan
Copy link
Contributor

pforhan commented Mar 17, 2014

I wonder if there is a way to layer some Phrase niceties on top of Android's plural support, somehow. There's lots and lots of rules built into android's plurals support, but as folks have found out, it still doesn't do everything we really want.

More concretely, I'm thinking Phrase could actually define a plural of its own, with default-language values for zero, one, two, few, many, other that correspond exactly to those keys.

Then Phrase could easily switch internally based on those values, maybe overlaying some logic as needed (people love their custom zeroes, for example). Support for native quantity strings may be desirable, or may be confusing, not sure.

@loganj
Copy link
Collaborator

loganj commented Mar 17, 2014

@pforhan Interesting. Do you have any concrete examples of cases where Android's pluralization is awkward? /ping @Turbo87, @denley, @dlew

@pforhan
Copy link
Contributor

pforhan commented Mar 17, 2014

Quick attempt at an API, for example:

enum QuantityMode {LANGUAGE, FORCE};

Phrase.forQuantity(resources)
  .zero(R.string.beer_none, FORCE) // Even if the language doesn't officially support it, use it.
  .one(R.string.beer_one) // we can just overload the builder methods to exclude the other parameter
  .two(R.string.beer_two)
  .few(R.string.some_beer)
  .many(R.string.beer_many)
  .quantity(quantity); // And this could put in an implicit putOptional() on "{quantity}", say.

@loganj Well, I mean awkward if we mix Android Quantities and Phrase Quantities. The only place where I've seen people longing for a behavior is for zero support across all languages.

@dlew
Copy link
Contributor

dlew commented Mar 17, 2014

The zero problem. Plurals in English only count "one" and "other" even if you might want a different phrasing for a particular case.

...Dang it pforhan. I'm posting anyways. :P

@edenman
Copy link
Collaborator

edenman commented Feb 2, 2016

FWIW, this is a pretty old issue, but: I don't know that Phrase needs to change to accomodate plurals. I'm doing this by just using plurals in the xml:

<plurals name="i_ate_some_tacos">
    <item quantity="one">I have eaten {num_tacos} taco.</item>
    <item quantity="other">I have eaten {num_tacos} tacos.</item>
</plurals>

And then:

String quantityString = res.getQuantityString(R.plurals.i_ate_some_tacos, numTacos);
textView.setText(Phrase.from(quantityString).put("num_tacos", numTacos).format());

If you didn't want to necessarily have the {num_tacos} in every quantity string, you could change to a putOptional.

@dlew
Copy link
Contributor

dlew commented Feb 3, 2016

That's a really good point, one that I hadn't considered before!

I've ended up using <plurals> because some translation services expect it (in particular, Transifex), so this is handy.

@loganj
Copy link
Collaborator

loganj commented Feb 4, 2016

Yeah, that's definitely sufficient and none of the other options have been compelling.

I could be convinced that a Phrase.fromQuantityString(int resId) might be nice, if anyone cares to float that PR. Otherwise I think we're good.

@loganj loganj closed this as completed Feb 4, 2016
@dlew
Copy link
Contributor

dlew commented Feb 4, 2016

How about this for a convincing argument: I'll make a PR, then you won't have to do the work. ;)

Though it'd actually have to be Phrase.fromQuantityString(Resources, int, int). Which might also mean we'd want Phrase.fromQuantityString(Context, int, int) as well.

@starkej2
Copy link

Did #21 ever get released?

@pforhan
Copy link
Contributor

pforhan commented May 28, 2020

not yet, I need to get the build working again, #40 for an attempt. But I have to work on it again, or alternately we should move to actions

@pforhan
Copy link
Contributor

pforhan commented May 28, 2020

and we should get #24 in before a release as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants