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

Add support for plurals in translations #6327

Open
akirk opened this issue Dec 13, 2016 · 15 comments
Open

Add support for plurals in translations #6327

akirk opened this issue Dec 13, 2016 · 15 comments

Comments

@akirk
Copy link
Contributor

akirk commented Dec 13, 2016

@frosty In #6208 you introduced the construct:

    if (count == 1) {
        self.noResultsView.titleText = NSLocalizedString(@"You have 1 hidden WordPress site.", "Message informing the user that all of their sites are currently hidden (singular)");
        self.noResultsView.messageText = NSLocalizedString(@"To manage it here, set it to visible.", @"Prompt asking user to make sites visible in order to use them in the app (singular)");
    } else {
        self.noResultsView.titleText = [NSString stringWithFormat:NSLocalizedString(@"You have %lu hidden WordPress sites.", "Message informing the user that all of their sites are currently hidden (plural)"), count];
        self.noResultsView.messageText = NSLocalizedString(@"To manage them here, set them to visible.", @"Prompt asking user to make sites visible in order to use them in the app (plural)");
    }

Unfortunately this cannot be translated properly because some languages don't just have a different plural for count != 1 (for example Russian, they use one form for 1, 21, 31; another one for 2, 3, 4; and yet another one for 5, 6, …). Please see Handling Noun Plurals and Units of Measurement in the iOS docs on how this can be done universally. Thanks!

@frosty
Copy link
Contributor

frosty commented Jan 30, 2017

Just an update: we're waiting on some GlotPress changes so it can handle stringsDict files before we do anything about this on our side.

@koke
Copy link
Member

koke commented Feb 17, 2017

More than supporting the specific format, I'm not sure if GlotPress can handle multiple files.
@akirk if we were to import a file with just the plurals in a format that GlotPress understands, wouldn't that remove all the other originals from the project?

@koke
Copy link
Member

koke commented Feb 17, 2017

One idea that's been growing on me today is to forget about adding new importers to GlotPress and handling everything on our side, merging all our strings into a big PO file, which GlotPress can understand perfectly.

Then we'd export each translation as a PO file as well, and use that and the original strings/stringsdict/xliff files generated by Xcode to generate the translated files that Xcode wants.

Also, neither genstrings or xcodebuild -exportLocalizations seem to be picking up plurals automatically, so we'd need to manually manage them or build a tool to extract them from the code.

@koke koke changed the title Blog List: Incorrect plural building Add support for plurals in translations Feb 17, 2017
@koke
Copy link
Member

koke commented Feb 17, 2017

Some candidates for plural support (there might be more):

iconv -f utf-16le -t utf-8 WordPress/Resources/en.lproj/Localizable.strings | grep '^".*%[^"]*s\b'
"%@ comments" = "%@ comments";
"%@ days" = "%@ days";
"%@ followers" = "%@ followers";
"%@ levels" = "%@ levels";
"%@ links" = "%@ links";
"%@ of views" = "%@ of views";
"%@ posts on %@" = "%1$@ posts on %2$@";
"%@ views" = "%@ views";
"%@ views per visitor" = "%@ views per visitor";
"%@ visitors" = "%@ visitors";
"%@ was reconnected." = "%@ was reconnected.";
"%d accounts" = "%d accounts";
"%d days" = "%d days";
"%d hours" = "%d hours";
"%d months" = "%d months";
"%d pixels" = "%d pixels";
"%d years" = "%d years";
"%i menu area in this theme" = "%i menu area in this theme";
"%i menu areas in this theme" = "%i menu areas in this theme";
"%i menus available" = "%i menus available";

@akirk
Copy link
Contributor Author

akirk commented Feb 17, 2017

More than supporting the specific format, I'm not sure if GlotPress can handle multiple files.
@akirk if we were to import a file with just the plurals in a format that GlotPress understands, wouldn't that remove all the other originals from the project?

Correct but not set in stone, this can be easily arranged that an imported file augments the existing strings and/or to import two files in one go. It could be done with a GlotPress plugin.

One idea that's been growing on me today is to forget about adding new importers to GlotPress and handling everything on our side, merging all our strings into a big PO file, which GlotPress can understand perfectly.

I like that a lot. A problem with generating the stringsdict on GlotPress side is that the PO way of defining plurals is with an "nplurals" formula, while stringsdict uses notions of one, some, few, many that would need to me mapped to the appriopriate plurals in each language which would require a whole new dependency of something like CLDR. This could be avoided with your approach.

@koke
Copy link
Member

koke commented Feb 24, 2017

Progress so far:

It looks like xgettext has some support for Objective-C (which also works on Swift). Unfortunately it doesn't pick up the existing translation comments. I decided to leave string extraction to genstrings for now and focus on plurals for the moment.

I have this new macro:

#define NSLocalizedStringPlural(singular, plural, number) NSLocalizedString(singular, @"")

What we can do with this, is to have genstrings skip the plurals, then do a second pass with xgettext to extract those. We'd have to specify translation comments gettext-style though:

// Translators: Message informing the user that all of their sites are currently hidden
self.noResultsView.titleText = NSLocalizedStringPlural(@"You have 1 hidden WordPress site.", @"You have %lu hidden WordPress sites.", count);
// Translators: Prompt asking user to make sites visible in order to use them in the app
self.noResultsView.messageText = NSLocalizedStringPlural(@"To manage it here, set it to visible.", @"To manage them here, set them to visible.", count);

And we can have xgettext generate a proper PO with that:

$ xgettext WordPress/Classes/ViewRelated/Blog/BlogListViewController.m -L ObjectiveC --from-code=utf-8 -o - -k -kNSLocalizedStringPlural:1,2 -cTranslators:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-24 17:24+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#. Translators: Message informing the user that all of their sites are currently hidden
#: WordPress/Classes/ViewRelated/Blog/BlogListViewController.m:269
#, c-format
msgid "You have 1 hidden WordPress site."
msgid_plural "You have %lu hidden WordPress sites."
msgstr[0] ""
msgstr[1] ""

#. Translators: Prompt asking user to make sites visible in order to use them in the app
#: WordPress/Classes/ViewRelated/Blog/BlogListViewController.m:271
msgid "To manage it here, set it to visible."
msgid_plural "To manage them here, set them to visible."
msgstr[0] ""
msgstr[1] ""

The next step would be to be able to convert that PO into a .stringsdict. This project might help with converting the plural forms from gettext to stringsdict, but we still need to figure out the right way to extract NSStringFormatValueTypeKey (i.e. if the format specifier is %d, %lu, %@,...).

Once we have that, I believe the rest will be easy, as the gettext tools to work with PO files are really good and support merging and comparing files really well. They even support reading and writing .strings files!

@akirk
Copy link
Contributor Author

akirk commented Feb 24, 2017

FYI work has commenced in GlotPress/GlotPress#666 to address that difference in plural definition which will allow the implementation of thr stringsdict format.

@stale
Copy link

stale bot commented Oct 13, 2018

This issue has been marked as stale and will be automatically closed. This happened because:

  • It has been inactive for the past year.
  • It isn't in a project or a milestone.
  • It hasn’t been labeled `[Pri] Blocker`, `[Pri] High`, or `good first issue`.

However, discussion is still welcome! If the issue is still valid, please leave a comment with a brief explanation so the issue can be reopened.

@stale stale bot added the [Status] Stale label Oct 13, 2018
@stale stale bot closed this as completed Oct 15, 2018
@ghost ghost reopened this Nov 6, 2018
@stale stale bot removed the [Status] Stale label Nov 6, 2018
@stale
Copy link

stale bot commented Nov 6, 2019

This issue has been marked as stale because:

  • It has been inactive for the past year.
  • It isn't in a project or a milestone.
  • It hasn’t been labeled [Pri] Blocker, [Pri] High, or good first issue.

Please comment with an update if you believe this issue is still valid or if it can be closed. This issue will also be reviewed for validity and priority (cc @designsimply).

@stale stale bot added the [Status] Stale label Nov 6, 2019
@designsimply
Copy link
Contributor

@akirk just checking in on this issue, I noticed GlotPress/GlotPress#666 is still open, is that a blocker for this issue in the iOS app?

@stale stale bot removed the [Status] Stale label Nov 6, 2019
@akirk
Copy link
Contributor Author

akirk commented Nov 6, 2019

Correct, unfortunately GlotPress development seems to have halted for now. I'll see if we can get it moving again.

@stale
Copy link

stale bot commented Nov 9, 2020

This issue has been marked as stale because:

  • It has been inactive for the past year.
  • It isn't in a project or a milestone.
  • It hasn’t been labeled [Pri] Blocker, [Pri] High, or good first issue.

Please comment with an update if you believe this issue is still valid or if it can be closed. This issue will also be reviewed for validity and priority during regularly scheduled triage sessions.

@stale stale bot added the [Status] Stale label Nov 9, 2020
@designsimply
Copy link
Contributor

Still valid! @akirk may I check in with you again about the status of GlotPress/GlotPress#666? I'm asking because this issue is stale, not because it's prioritized. So an update to say it's still in progress is acceptable and that will make it so we put it on hold again but check back in on it in a year if it goes stale again. 🙂

@stale stale bot removed the [Status] Stale label Nov 17, 2020
@stale
Copy link

stale bot commented Apr 29, 2022

This issue has been marked as stale because:

  • It has been inactive for the past year.
  • It isn't in a project or a milestone.
  • It hasn’t been labeled [Pri] Blocker, [Pri] High, or good first issue.

Please comment with an update if you believe this issue is still valid or if it can be closed. This issue will also be reviewed for validity and priority during regularly scheduled triage sessions.

@dangermattic
Copy link
Collaborator

Thanks for reporting! 👍

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

No branches or pull requests

8 participants