This commit is contained in:
Muhammad Mohiuddin
2023-08-03 00:54:04 +02:00
parent dc0adfcfbb
commit 8bc7c5cf8b
5 changed files with 101 additions and 77 deletions

View File

@@ -7,7 +7,9 @@ import 'src/ru.dart' as ru;
/// count is never null.
///
typedef CategoryResolver = QuantityCategory Function(
int count, QuantityType type);
int count,
QuantityType type,
);
enum QuantityCategory { zero, one, two, few, many, other }
@@ -30,8 +32,17 @@ String plural(
String? many,
String? other,
}) {
return _resolvePlural(count, languageCode, QuantityType.cardinal,
zero: zero, one: one, two: two, few: few, many: many, other: other);
return _resolvePlural(
count,
languageCode,
QuantityType.cardinal,
zero: zero,
one: one,
two: two,
few: few,
many: many,
other: other,
);
}
///
@@ -47,8 +58,17 @@ String cardinal(
String? many,
String? other,
}) {
return _resolvePlural(count, languageCode, QuantityType.cardinal,
zero: zero, one: one, two: two, few: few, many: many, other: other);
return _resolvePlural(
count,
languageCode,
QuantityType.cardinal,
zero: zero,
one: one,
two: two,
few: few,
many: many,
other: other,
);
}
///
@@ -64,8 +84,17 @@ String ordinal(
String? many,
String? other,
}) {
return _resolvePlural(count, languageCode, QuantityType.ordinal,
zero: zero, one: one, two: two, few: few, many: many, other: other);
return _resolvePlural(
count,
languageCode,
QuantityType.ordinal,
zero: zero,
one: one,
two: two,
few: few,
many: many,
other: other,
);
}
Map<String, CategoryResolver> _resolverRegistry = {
@@ -87,36 +116,24 @@ String _resolvePlural(
}) {
final c = _resolveCategory(languageCode, count, type);
many ??= other;
switch (c) {
case QuantityCategory.zero:
return _firstNotNull(zero, many);
case QuantityCategory.one:
return _firstNotNull(one, many);
case QuantityCategory.two:
return _firstNotNull(two, many);
case QuantityCategory.few:
return _firstNotNull(few, many);
case QuantityCategory.many:
return _firstNotNull(many, other);
case QuantityCategory.other:
return _firstNotNull(other, many);
}
return switch (c) {
QuantityCategory.zero => _firstNotNull(zero, many),
QuantityCategory.one => _firstNotNull(one, many),
QuantityCategory.two => _firstNotNull(two, many),
QuantityCategory.few => _firstNotNull(few, many),
QuantityCategory.many => _firstNotNull(many, other),
QuantityCategory.other => _firstNotNull(other, many),
};
}
QuantityCategory _defaultResolver(int count, QuantityType type) {
switch (count) {
case 0:
return QuantityCategory.zero;
case 1:
return QuantityCategory.one;
case 2:
return QuantityCategory.two;
case 3:
return QuantityCategory.few;
case 4:
return QuantityCategory.few;
}
return QuantityCategory.other;
return switch (count) {
0 => QuantityCategory.zero,
1 => QuantityCategory.one,
2 => QuantityCategory.two,
3 || 4 => QuantityCategory.few,
_ => QuantityCategory.other,
};
}
QuantityCategory _resolveCategory(
@@ -124,14 +141,10 @@ QuantityCategory _resolveCategory(
int count,
QuantityType type,
) {
CategoryResolver resolver;
resolver = _resolverRegistry[languageCode] ??= _defaultResolver;
final resolver = _resolverRegistry[languageCode] ?? _defaultResolver;
return resolver(count, type);
}
String _firstNotNull(String? a, String? b) {
if (a != null) return a;
if (b != null) return b;
return '???';
return a ?? b ?? '???';
}

View File

@@ -2,10 +2,9 @@ library i18n;
import 'package:yaml/yaml.dart';
import 'metadata.dart';
import 'string_ext.dart';
part 'model.dart';
Pattern twoCharsLower = RegExp('^[a-z]{2}\$');
Pattern twoCharsUpper = RegExp('^[A-Z]{2}\$');
@@ -19,24 +18,34 @@ String generateDartContentFromYaml(Metadata meta, String yamlContent) {
final output = StringBuffer();
output.writeln('// GENERATED FILE, do not edit!');
output.writeln('// ignore_for_file: annotate_overrides, non_constant_identifier_names, prefer_single_quotes, unused_element, unused_field');
output.writeln(
'// ignore_for_file: annotate_overrides, non_constant_identifier_names, prefer_single_quotes, unused_element, unused_field',
);
output.writeln('import \'package:i18n/i18n.dart\' as i18n;');
if (meta.defaultFileName != null) {
output.writeln("import '${meta.defaultFileName}';");
}
output.writeln('\tString get _languageCode => \'${meta.languageCode}\';');
output.writeln(
'\tString _plural(int count, {String? zero, String? one, String? two, String? few, String? many, String? other}) =>');
'\tString get _languageCode => \'${meta.languageCode}\';',
);
output.writeln(
'\ti18n.plural(count, _languageCode, zero:zero, one:one, two:two, few:few, many:many, other:other);');
'\tString _plural(int count, {String? zero, String? one, String? two, String? few, String? many, String? other}) =>',
);
output.writeln(
'String _ordinal(int count, {String? zero, String? one, String? two, String? few, String? many, String? other}) =>');
'\ti18n.plural(count, _languageCode, zero: zero, one: one, two: two, few: few, many: many, other: other);',
);
output.writeln(
'\ti18n.ordinal(count, _languageCode, zero:zero, one:one, two:two, few:few, many: many, other: other,);');
'String _ordinal(int count, {String? zero, String? one, String? two, String? few, String? many, String? other}) =>',
);
output.writeln(
'String _cardinal(int count, {String? zero, String? one, String? two, String? few, String? many, String? other,}) =>');
'\ti18n.ordinal(count, _languageCode, zero: zero, one: one, two: two, few: few, many: many, other: other,);',
);
output.writeln(
'\ti18n.cardinal(count, _languageCode, zero:zero, one:one, two:two, few:few, many: many, other: other,);');
'String _cardinal(int count, {String? zero, String? one, String? two, String? few, String? many, String? other,}) =>',
);
output.writeln(
'\ti18n.cardinal(count, _languageCode, zero: zero, one: one, two: two, few: few, many: many, other: other,);',
);
output.writeln('');
for (final translation in translations) {
@@ -88,7 +97,8 @@ Metadata generateMessageObjectName(String fileName) {
languageCode = nameParts[1];
if (twoCharsLower.allMatches(languageCode).length != 1) {
throw Exception(
'Wrong language code "$languageCode" in file name "$fileName". Language code must match $twoCharsLower');
'Wrong language code "$languageCode" in file name "$fileName". Language code must match $twoCharsLower',
);
}
languageCode = languageCode;
localeName = languageCode;
@@ -97,7 +107,8 @@ Metadata generateMessageObjectName(String fileName) {
final countryCode = nameParts[2];
if (twoCharsUpper.allMatches(countryCode).length != 1) {
throw Exception(
'Wrong country code "$countryCode" in file name "$fileName". Country code must match $twoCharsUpper');
'Wrong country code "$countryCode" in file name "$fileName". Country code must match $twoCharsUpper',
);
}
localeName = '${languageCode}_$countryCode';
}

View File

@@ -1,4 +1,4 @@
part of i18n;
import 'package:yaml/yaml.dart';
class Metadata {
final Metadata? parent;
@@ -20,7 +20,7 @@ class Metadata {
});
Metadata nest(String namePrefix) {
final result = Metadata(
return Metadata(
parent: this,
isDefault: isDefault,
defaultObjectName: '$namePrefix$defaultObjectName',
@@ -29,13 +29,12 @@ class Metadata {
localeName: localeName,
languageCode: languageCode,
);
return result;
}
}
class Translation {
Metadata metadata;
YamlMap content;
final Metadata metadata;
final YamlMap content;
Translation(this.metadata, this.content);
}

View File

@@ -1,5 +1,6 @@
import 'package:i18n/i18n.dart';
import 'package:i18n/src/i18n_impl.dart';
import 'package:i18n/src/metadata.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';

View File

@@ -25,29 +25,29 @@ void main() => group('StringX', () {
});
test('containsReference return true if there is a reference', () {
expect(r'$name'.containsReference, isTrue);
expect(r'\$name'.containsReference, isFalse);
expect(r'name'.containsReference, isFalse);
expect(r'300\$'.containsReference, isFalse);
expect(() => r'_\$$name'.containsReference, throwsArgumentError);
});
expect(r'$name'.containsReference, isTrue);
expect(r'\$name'.containsReference, isFalse);
expect(r'name'.containsReference, isFalse);
expect(r'300\$'.containsReference, isFalse);
expect(() => r'_\$$name'.containsReference, throwsArgumentError);
});
test('convert name works if there are no _ in the name', () {
expect('message'.convertName(), 'message');
});
test('convert name works if there are no _ in the name', () {
expect('message'.convertName(), 'message');
});
test('convert name works if there is 1 _ in the name', () {
expect('message_de'.convertName(), 'messageDe');
});
test('convert name works if there is 1 _ in the name', () {
expect('message_de'.convertName(), 'messageDe');
});
test('convert name works if there are 2 _ in the name', () {
expect('message_en_us'.convertName(), 'messageEnUs');
});
test('convert name works if there are 2 _ in the name', () {
expect('message_en_us'.convertName(), 'messageEnUs');
});
test('convert name works if there are many _ in the name', () {
expect(
test('convert name works if there are many _ in the name', () {
expect(
() => 'translation_message_en_us'.convertName(),
throwsArgumentError,
);
});
throwsArgumentError,
);
});
});