marcglasberg / i18n_extension

Flutter package: Easy and powerful internationalization using Dart extensions.
Other
294 stars 64 forks source link

Incorrect plural forms from po files #115

Open maciejpos opened 2 years ago

maciejpos commented 2 years ago

In some languages (e.g. Czech, Polish), there are 3 plural forms. e.g. for the English word "character" (Polish: 'znak') the 3 possible plurals as follows: znaków, znak, znaki.

Above plurals appear for following numbers accordingly: 0 : znaków 1: znak 2,3,4: znaki 5,6,7,8,..21: znaków 22-25: znaki

The Plural-Forms rules are correctly defined in the following pl_pl.po file:

msgid ""
msgstr ""
"Project-Id-Version: poedit\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
"X-Generator: Poedit 3.1\n"

msgid "The file contains "
msgstr "Plik zawiera "

#. This is an example of translation of a plural form of en_us word 'character' into pl_pl 'znak'
msgid "%d character"
msgid_plural "%d characters"
msgstr[0] "%d znak"
msgstr[1] "%d znaki"
msgstr[2] "%d znaków"

[Poedit 3.1 screenshot] i18n_extension_plural_issue_poedit31_screen

The po file is loaded using the following code:

import 'package:i18n_extension/i18n_extension.dart';
import 'package:i18n_extension/io/import.dart';
import 'package:logger/logger.dart';

class MyI18n {
  static TranslationsByLocale translations = Translations.byLocale("en_US");

  static Future<void> loadTranslations() async {
    translations +=
    await GettextImporter().fromAssetDirectory("assets/locales");
    logger.i('\n\n***********\nMain. Init. Load Translations \n$translations\n*************\n\n');
  }
}

extension Localization on String {
  String get i18n => localize(this, MyI18n.translations);
  String fill(List<Object> params) => localizeFill(this, params);
  String plural(value) => localizePlural(value, this, MyI18n.translations);
  String version(Object modifier) => localizeVersion(modifier, this, MyI18n.translations);
  Map<String?, String> allVersions() => localizeAllVersions(this, MyI18n.translations);
}

And the i18n_extension translations in the code are as follows:

    Text('The file contains '.i18n
        + '%d character'.i18n.plural(0) + '.   [Not OK, should be: \'znaków\']'),
    Text('The file contains '.i18n
        + '%d character'.i18n.plural(1) + '.   [OK, should be: \'znak\']'),
    Text('The file contains '.i18n
        + '%d character'.i18n.plural(2) + '.   [OK, should be: \'znaki\']'),
    Text('The file contains '.i18n
        + '%d character'.i18n.plural(5) + '.   [Not OK, should be: \'znaków\']'),
    Text('The file contains '.i18n
        + '%d character'.i18n.plural(55) + '.   [Not OK, should be: \'znaków\']'),
    Text('The file contains '.i18n
        + '%d character'.i18n.plural(52) + '.   [OK, should be: \'znaki\']'),

The output in the app is as follows:

i18n_extension_plural_issue_app_screen

[ISSUE] The problem is that the plural modifier is not taking into account the Plural-Forms definition from po file. Do you have any idea how to fix it?

marcglasberg commented 1 year ago

The PO importer was contributed by @bauerj

bauerj commented 1 year ago

Thank you. Indeed, this is currently not implemented.

The upstream library (gettext_parser) correctly identified the plurals as defined in the .PO file.

However, I don't think it's currently possible to use arbitrary plural definitions like necessary some languages. Polish plurals could be defined by using 26 calls to .times (although probably unefficient).


@marcglasberg: Is it currently possible (e.g. using the .times modifier) to define plural translations for e.g. Arabic?

image Source: https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html#ar