mirror of
https://github.com/chenasraf/i18n.git
synced 2026-05-17 17:38:07 +00:00
refactor
This commit is contained in:
@@ -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 ?? '???';
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user