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

Feature/basic plurals support #20

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,26 @@ String description({
@required String var1,
})
```

If the variables are not provided, the String will be given without replacing the variables placeholders.

### Plurals

Plurals are possible thanks to dart's [Intl.plural](https://api.flutter.dev/flutter/intl/Intl/plural.html) method. In order to select the correct plural form, six alternatives must be given: `zero`, `one`, `two`, `few`, `many` and `other`. An explanation about these alternatives can be found [here](http://cldr.unicode.org/index/cldr-spec/plural-rules).

These alternatives must be given in the form `|alt1:alt2:alt3:alt4:alt5:alt6|`, that is, surrounded by `|` and separated with `:`.

```
pluralTest,Time left: %seconds$d |seconds:second:seconds:seconds:seconds:seconds|,Verbleibende Zeit: %seconds$d |Sekunden:Sekunde:Sekunden:Sekunden:Sekunden:Sekunden|,Pozostały czas: %seconds$d |sekund:sekunda:sekundy:sekund:sekund:sekund|
```

`pluralTest` would then be parsed with the following function signature: `String pluralTest({@required int seconds})` and could be used as follows:

|seconds|en|de|pl|
|:-:|-|-|-|
|0|Time left: 0 seconds|Verbleibende Zeit: 0 Sekunden|Pozostały czas: 0 sekund|
|1|Time left: 1 second|Verbleibende Zeit: 1 Sekunde|Pozostały czas: 1 sekunda|
|2|Time left: 2 seconds|Verbleibende Zeit: 2 Sekunden|Pozostały czas: 2 sekundy|
|5|Time left: 5 seconds|Verbleibende Zeit: 5 Sekunden|Pozostały czas: 5 sekund|

Note that only one plural per key is presently supported.
36 changes: 36 additions & 0 deletions example/lib/i18n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class Home extends StatelessWidget {
Text(I18n.of(context).appTitle),
Text(I18n.of(context).description(var1: '2')),
Text(I18n.of(context).littleTest(age: 32)),
Text(I18n.of(context).pluralTest(seconds: 24)),
Text(I18n.of(context).pluralTest(seconds: 1)),
],
),
),
Expand Down
1 change: 1 addition & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies:
flutter_localizations:
sdk: flutter
cupertino_icons: ^0.1.2
intl: ^0.16.1

dev_dependencies:
flappy_translator:
Expand Down
3 changes: 2 additions & 1 deletion example/test.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ keys,fr,en,es,de_CH
appTitle,Ma super application,My awesome application,Mi gran application,Meine tolle App
subtitle,Un sous titre,A subtitle,Un subtitulò,Ein Untertitel
description,Un texte avec une variable : %1$s,Text with a variable: %1$s,Un texto con una variable : %1$s,Text mit einer Variable: %1$s
littleTest,"Voici, pour l'exemple, ""un test"" avec la variable %age$d","Here is, for the example, ""a test"" with the variable %age$d","Aqui esta, por ejemplo, ""una prueba"" con la variable %age$d","Hier ist, zum Beispiel, ""ein Test"" mit der Variable %age$d"
littleTest,"Voici, pour l'exemple, ""un test"" avec la variable %age$d","Here is, for the example, ""a test"" with the variable %age$d","Aqui esta, por ejemplo, ""una prueba"" con la variable %age$d","Hier ist, zum Beispiel, ""ein Test"" mit der Variable %age$d"
pluralTest,Temps restant: %seconds$d |seconde:second:secondes:secondes:secondes:secondes|,Time left: %seconds$d |seconds:second:seconds:seconds:seconds:seconds|,Tiempo que queda: %seconds$d |segundos:segundo:segundos:segundos:segundos:segundos|,Verbleibende Zeit: %seconds$d |Sekunden:Sekunde:Sekunden:Sekunden:Sekunden:Sekunden|
Binary file modified example/test.xlsx
Binary file not shown.
47 changes: 46 additions & 1 deletion lib/src/services/code_generation/code_generator.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import 'dart:io';

import 'package:dart_style/dart_style.dart';
import 'package:flappy_translator/src/utils/flappy_logger.dart';

import '../../configs/constants.dart' as constants;
import '../../configs/default_settings.dart';
Expand All @@ -10,6 +13,7 @@ class CodeGenerator {
final String _quoteString;
final bool replaceNoBreakSpaces;
final _parametersRegex = RegExp(r'(\%[[0-9a-zA-Z]+]*\$(d|s))');
final _pluralsRegexp = RegExp(r'\|(.*?)\|');

String _template;
List<Map<String, String>> _maps;
Expand Down Expand Up @@ -77,8 +81,15 @@ class CodeGenerator {
}

void addField(String key, String defaultWord, List<String> words) {
if (_pluralsRegexp.allMatches(defaultWord).length > 1) {
FlappyLogger.logError(
'Key $key contains multiple plurals. Only one plural per key is supported.');
exit(0);
}

var result = '';
final hasParameters = _parametersRegex.hasMatch(defaultWord);
final hasPlural = _pluralsRegexp.hasMatch(defaultWord);
if (hasParameters) {
var parameters = '';
final matches = _parametersRegex.allMatches(defaultWord).toList();
Expand All @@ -103,8 +114,42 @@ class CodeGenerator {
''';
}

if (hasPlural) {
final plurals = _pluralsRegexp
.firstMatch(defaultWord)
.group(0)
.replaceAll('|', '')
.split(':');
if (plurals.length != 6) {
FlappyLogger.logError(
'Incorrect number of plurals given in $defaultWord. Must give 6.');
exit(0);
}

final varName =
_getParameterNameFromPlaceholder(matches.first.group(0));
result += '''
final _pluralsRegExp = RegExp(r"\\\|(.*?)\\\|");
final plurals = _pluralsRegExp.firstMatch(_text).group(0).replaceAll('|', '').split(':');
if(plurals.length != 6) {
return 'Issue with key $key. Incorrect number of plurals.';
}
return Intl.plural(
$varName,
zero: _text.replaceAll(_pluralsRegExp, plurals[0]),
one: _text.replaceAll(_pluralsRegExp, plurals[1]),
two: _text.replaceAll(_pluralsRegExp, plurals[2]),
few: _text.replaceAll(_pluralsRegExp, plurals[3]),
many: _text.replaceAll(_pluralsRegExp, plurals[4]),
other: _text.replaceAll(_pluralsRegExp, plurals[5]),
);

''';
} else {
result += 'return _text;';
}

result += '''
return _text;

}
''';
Expand Down
1 change: 1 addition & 0 deletions lib/src/services/code_generation/template.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ abstract class Template {
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

/// A class generated by flappy_translator package containing localized strings
class #CLASS_NAME# {
Expand Down
3 changes: 3 additions & 0 deletions test/services/code_generation/code_generator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ void main() {
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

/// A class generated by flappy_translator package containing localized strings
class I18n {
Expand Down Expand Up @@ -188,6 +189,7 @@ class I18nDelegate extends LocalizationsDelegate<I18n> {
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

/// A class generated by flappy_translator package containing localized strings
class I18n {
Expand Down Expand Up @@ -261,6 +263,7 @@ class I18nDelegate extends LocalizationsDelegate<I18n> {
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

/// A class generated by flappy_translator package containing localized strings
class I18n {
Expand Down
7 changes: 7 additions & 0 deletions test/services/parsing/csv_parser_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ void main() {
"Aqui esta, por ejemplo, \"una prueba\" con la variable %age\$d",
"Hier ist, zum Beispiel, \"ein Test\" mit der Variable %age\$d"
],
[
'pluralTest',
'Temps restant: %seconds\$d |seconde:second:secondes:secondes:secondes:secondes|',
'Time left: %seconds\$d |seconds:second:seconds:seconds:seconds:seconds|',
'Tiempo que queda: %seconds\$d |segundos:segundo:segundos:segundos:segundos:segundos|',
'Verbleibende Zeit: %seconds\$d |Sekunden:Sekunde:Sekunden:Sekunden:Sekunden:Sekunden|'
],
]);
});
}
7 changes: 7 additions & 0 deletions test/services/parsing/excel_parser_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ void main() {
"Aqui esta, por ejemplo, \"una prueba\" con la variable %age\$d",
"Hier ist, zum Beispiel, \"ein Test\" mit der Variable %age\$d"
],
[
'pluralTest',
'Temps restant: %seconds\$d |seconde:second:secondes:secondes:secondes:secondes|',
'Time left: %seconds\$d |seconds:second:seconds:seconds:seconds:seconds|',
'Tiempo que queda: %seconds\$d |segundos:segundo:segundos:segundos:segundos:segundos|',
'Verbleibende Zeit: %seconds\$d |Sekunden:Sekunde:Sekunden:Sekunden:Sekunden:Sekunden|'
],
]);
});
}