Skip to content

Commit

Permalink
start localization
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobaraujo7 committed Aug 27, 2024
1 parent 40aa858 commit 7d0eeed
Show file tree
Hide file tree
Showing 18 changed files with 322 additions and 94 deletions.
2 changes: 1 addition & 1 deletion example/lib/domain/validations/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ extension CustomValidPasswordValidator on SimpleValidationBuilder<String> {
.minLength(5)
.mustHaveLowercase()
.mustHaveUppercase()
.mustHaveNumbers()
.mustHaveNumber()
.mustHaveSpecialCharacter();
}
}
Expand Down
24 changes: 24 additions & 0 deletions lib/lucid_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,31 @@
///
library lucid_validation;

import 'lucid_validation.dart';

export 'src/localization/language_manager.dart';
export 'src/localization/localization.dart';
export 'src/lucid_validation_builder.dart';
export 'src/lucid_validator.dart';
export 'src/types/types.dart';
export 'src/validations/validations.dart';

sealed class LucidValidation {
static final global = _GlobalConfig(
language: EnglishLanguage(),
languageManager: DefaultLanguageManager(),
cascadeMode: CascadeMode.continueExecution,
);
}

class _GlobalConfig {
LanguageManager languageManager;
CascadeMode cascadeMode;
Language language;

_GlobalConfig({
required this.languageManager,
required this.cascadeMode,
required this.language,
});
}
59 changes: 59 additions & 0 deletions lib/src/localization/language.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
abstract class Language {
final String culture;

static const code = (
equalTo: 'equalTo',
greaterThan: 'greaterThan',
isEmpty: 'isEmpty',
isNotNull: 'isNotNull',
isNull: 'isNull',
lessThan: 'lessThan',
matchesPattern: 'matchesPattern',
max: 'max',
maxLength: 'maxLength',
min: 'min',
minLength: 'minLength',
mustHaveLowercase: 'mustHaveLowercase',
mustHaveNumber: 'mustHaveNumber',
mustHaveSpecialCharacter: 'mustHaveSpecialCharacter',
mustHaveUppercase: 'mustHaveUppercase',
notEmpty: 'notEmpty',
notEqualTo: 'notEqualTo',
range: 'range',
validCEP: 'validCEP',
validCPF: 'validCPF',
validCNPJ: 'validCNPJ',
validCreditCard: 'validCreditCard',
validEmail: 'validEmail',
);

Language(this.culture);

final _translations = <String, String>{
code.equalTo: "'{PropertyName}' must be equal to '{ComparisonValue}'.",
code.greaterThan: "'{PropertyName}' must be greater than '{ComparisonValue}'.",
code.isEmpty: "'{PropertyName}' must be empty.",
code.isNotNull: "'{PropertyName}' must not be empty.",
code.isNull: "'{PropertyName}' must be empty.",
code.lessThan: "'{PropertyName}' must be less than '{ComparisonValue}'.",
code.matchesPattern: "'{PropertyName}' is not in the correct format.",
code.max: "'{PropertyName}' must be less than or equal to {MaxValue}. You entered {PropertyValue}.",
code.maxLength: "The length of '{PropertyName}' must be {MaxLength} characters or fewer. You entered {TotalLength} characters.",
code.min: "'{PropertyName}' must be greater than or equal to {MinValue}. You entered {PropertyValue}.",
code.minLength: "The length of '{PropertyName}' must be at least {MinLength} characters. You entered {TotalLength} characters.",
code.mustHaveLowercase: "'{PropertyName}' must have at least one lowercase letter.",
code.mustHaveNumber: "'{PropertyName}' must have at least one digit ('0'-'9').",
code.mustHaveSpecialCharacter: "'{PropertyName}' must have at least one non-alphanumeric character.",
code.mustHaveUppercase: "'{PropertyName}' must have at least one uppercase letter.",
code.notEmpty: "'{PropertyName}' must not be empty.",
code.notEqualTo: "'{PropertyName}' must not be equal to '{ComparisonValue}'.",
code.range: "'{PropertyName}' must be between {From} and {To}. You entered {PropertyValue}.",
code.validCEP: "'{PropertyName}' is not a valid CEP.",
code.validCPF: "'{PropertyName}' is not a valid CPF.",
code.validCNPJ: "'{PropertyName}' is not a valid CNPJ.",
code.validCreditCard: "'{PropertyName}' is not a valid credit card number.",
code.validEmail: "'{PropertyName}' is not a valid email address.",
};

String? getTranslation(String key) => _translations[key];
}
27 changes: 27 additions & 0 deletions lib/src/localization/language_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import '../../lucid_validation.dart';

abstract class LanguageManager {
final _globalTranslations = <String, Map<String, String>>{};

Language get currentLanguage => LucidValidation.global.language;

void addTranslation(String culture, String code, String value) {
if (!_globalTranslations.containsKey(culture)) {
_globalTranslations[culture] = {};
}
_globalTranslations[culture]![code] = value;
}

String translate(String key, [Map<String, String> parameters = const {}]) {
final culture = currentLanguage.culture;
final translations = _globalTranslations[culture] ?? {};
var message = translations[key] ?? currentLanguage.getTranslation(key) ?? key;
for (var key in parameters.keys) {
final value = parameters[key]!;
message = message.replaceAll('{$key}', value);
}
return message;
}
}

class DefaultLanguageManager extends LanguageManager {}
5 changes: 5 additions & 0 deletions lib/src/localization/languages/english_language.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import '../language.dart';

class EnglishLanguage extends Language {
EnglishLanguage() : super('en');
}
3 changes: 3 additions & 0 deletions lib/src/localization/localization.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'language.dart';
export 'language_manager.dart';
export 'languages/english_language.dart';
43 changes: 25 additions & 18 deletions lib/src/lucid_validation_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ abstract class LucidValidationBuilder<TProp, Entity> {
/// builder.must((username) => username.isNotEmpty, 'Username cannot be empty');
/// ```
LucidValidationBuilder<TProp, Entity> must(bool Function(TProp value) validator, String message, String code) {
ValidationError? callback(entity) {
final value = _selector(entity);
ValidationError? callback(value, entity) {
if (validator(value)) {
return null;
}
Expand All @@ -88,9 +87,7 @@ abstract class LucidValidationBuilder<TProp, Entity> {
);
}

_rules.add(callback);

return this;
return use(callback);
}

/// Adds a validation rule that checks if the [TProp] value satisfies the [validator] condition,
Expand Down Expand Up @@ -119,21 +116,31 @@ abstract class LucidValidationBuilder<TProp, Entity> {
String message,
String code,
) {
ValidationError? callback(entity) {
final value = _selector(entity);
if (validator(value, entity)) {
return null;
}

return ValidationError(
message: message,
key: key,
code: code,
);
}
return use(
(value, entity) {
if (validator(value, entity)) {
return null;
}

_rules.add(callback);
return ValidationError(
message: message,
key: key,
code: code,
);
},
);
}

/// Adds a validation rule to the LucidValidationBuilder.
///
/// The [rule] parameter is a function that takes an [Entity] object as input and returns a [ValidationError] object.
/// This method adds the [rule] to the list of validation rules in the LucidValidationBuilder.
///
/// Returns the current instance of the LucidValidationBuilder.
LucidValidationBuilder<TProp, Entity> use(
ValidationError? Function(TProp value, Entity entity) rule,
) {
_rules.add((entity) => rule(_selector(entity), entity));
return this;
}

Expand Down
26 changes: 21 additions & 5 deletions lib/src/validations/equal_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,30 @@ extension EqualValidation<T, E> on LucidValidationBuilder<T, E> {
/// .equalTo((user) => user.password);
///
/// ```
LucidValidationBuilder<T, E> equalTo(T Function(E entity) predicate, {String message = r'Must be equal', String code = 'equal_error'}) {
return mustWith(
///
/// String format args:
/// - **{PropertyName}**: The name of the property.
/// - **{ComparisonValue}**: The value to compare against.
///
LucidValidationBuilder<T, E> equalTo(
T Function(E entity) predicate, {
String? message,
String? code,
}) {
return use(
(value, entity) {
final comparison = predicate(entity);
return value == comparison;
if (value == comparison) return null;

final currentCode = code ?? Language.code.equalTo;
final currentMessage = message ??
LucidValidation.global.languageManager.translate(currentCode, {
'PropertyName': key,
'ComparisonValue': '$comparison',
});

return ValidationError(message: currentMessage, code: currentCode);
},
message,
code,
);
}
}
30 changes: 23 additions & 7 deletions lib/src/validations/greater_than_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extension GreaterThanValidation on SimpleValidationBuilder<num> {
/// Adds a validation rule that checks if the [num] is greater than [minValue].
///
/// [minValue] is the value that the number must be greater than.
/// [message] is the error message returned if the validation fails. Defaults to "Must be greater than $minValue".
/// [message] is the error message returned if the validation fails.
/// [code] is an optional error code for translation purposes.
///
/// Returns the [LucidValidationBuilder] to allow for method chaining.
Expand All @@ -19,11 +19,27 @@ extension GreaterThanValidation on SimpleValidationBuilder<num> {
/// ruleFor((user) => user.age, key: 'age')
/// .greaterThan(18);
/// ```
SimpleValidationBuilder<num> greaterThan(num minValue, {String message = r'Must be greater than $minValue', String code = 'greater_than'}) {
return must(
(value) => value > minValue,
message.replaceAll('$minValue', minValue.toString()),
code,
);
///
/// String format args:
/// - **{PropertyName}**: The name of the property.
/// - **{ComparisonValue}**: The value to compare against.
///
SimpleValidationBuilder<num> greaterThan(
num minValue, {
String? message,
String? code,
}) {
return use((value, entity) {
if (value > minValue) return null;

final currentCode = code ?? Language.code.greaterThan;
final currentMessage = message ??
LucidValidation.global.languageManager.translate(currentCode, {
'PropertyName': key,
'ComparisonValue': '$minValue',
});

return ValidationError(message: currentMessage, code: currentCode);
});
}
}
23 changes: 16 additions & 7 deletions lib/src/validations/is_empty_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ part of 'validations.dart';
extension IsEmptyValidation on SimpleValidationBuilder<String> {
/// Adds a validation rule that checks if the [String] is empty.
///
/// [message] is the error message returned if the validation fails. Defaults to "Must be empty".
/// [message] is the error message returned if the validation fails.
/// [code] is an optional error code for translation purposes.
///
/// Returns the [LucidValidationBuilder] to allow for method chaining.
Expand All @@ -18,11 +18,20 @@ extension IsEmptyValidation on SimpleValidationBuilder<String> {
/// ruleFor((user) => user.name, key: 'name')
/// .isEmpty();
/// ```
SimpleValidationBuilder<String> isEmpty({String message = 'Must be empty', String code = 'must_be_empty'}) {
return must(
(value) => value.isEmpty,
message,
code,
);
/// String format args:
/// - **{PropertyName}**: The name of the property.
///
SimpleValidationBuilder<String> isEmpty({String? message, String? code}) {
return use((value, entity) {
if (value.isEmpty) return null;

final currentCode = code ?? Language.code.isEmpty;
final currentMessage = message ??
LucidValidation.global.languageManager.translate(currentCode, {
'PropertyName': key,
});

return ValidationError(message: currentMessage, code: currentCode);
});
}
}
25 changes: 18 additions & 7 deletions lib/src/validations/is_not_null_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ part of 'validations.dart';
///
/// This extension adds an `isNotNull` method that can be used to ensure that a value
/// is not null.
extension IsNotNullValidation<T> on SimpleValidationBuilder<T> {
extension IsNotNullValidation<T> on SimpleValidationBuilder<T?> {
/// Adds a validation rule that checks if the value is not null.
///
/// [message] is the error message returned if the validation fails. Defaults to "Cannot be null".
/// [message] is the error message returned if the validation fails.
/// [code] is an optional error code for translation purposes.
///
/// Returns the [LucidValidationBuilder] to allow for method chaining.
Expand All @@ -18,11 +18,22 @@ extension IsNotNullValidation<T> on SimpleValidationBuilder<T> {
/// ruleFor((user) => user.name, key: 'name') // required field
/// .isNotNull();
/// ```
SimpleValidationBuilder<T> isNotNull({String message = 'Cannot be null', String code = 'cannot_be_null'}) {
return must(
(value) => value != null,
message,
code,
/// String format args:
/// - **{PropertyName}**: The name of the property.
///
SimpleValidationBuilder<T?> isNotNull({String? message, String? code}) {
return use(
(value, entity) {
if (value != null) return null;

final currentCode = code ?? Language.code.isNotNull;
final currentMessage = message ??
LucidValidation.global.languageManager.translate(currentCode, {
'PropertyName': key,
});

return ValidationError(message: currentMessage, code: currentCode);
},
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ extension MustHaveNumbersValidation on SimpleValidationBuilder<String> {
/// ruleFor((user) => user.password, key: 'password')
/// .mustHaveNumbers();
/// ```
SimpleValidationBuilder<String> mustHaveNumbers({String message = 'Must contain at least one numeric digit', String code = 'must_have_numbers'}) {
SimpleValidationBuilder<String> mustHaveNumber({String message = 'Must contain at least one numeric digit', String code = 'must_have_numbers'}) {
return must(
(value) => RegExp(r'[0-9]').hasMatch(value),
message,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/validations/validations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ part 'max_validation.dart';
part 'min_length_validation.dart';
part 'min_validation.dart';
part 'must_have_lowercase_validation.dart';
part 'must_have_numbers_validation.dart';
part 'must_have_number_validation.dart';
part 'must_have_special_character_validation.dart';
part 'must_have_uppercase_validation.dart';
part 'not_empty_validation.dart';
Expand Down
Loading

0 comments on commit 7d0eeed

Please sign in to comment.