master #81
@ -24,14 +24,14 @@ import 'package:wyatt_i18n/src/core/utils/yaml_parser.dart';
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// This enum is used to determine the parser to use for a given i18n file.
 | 
					/// This enum is used to determine the parser to use for a given i18n file.
 | 
				
			||||||
enum Format {
 | 
					enum Format {
 | 
				
			||||||
  /// JSON i18 file format.
 | 
					  /// JSON i18n file format.
 | 
				
			||||||
  json,
 | 
					  json,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// YAML i18 file format.
 | 
					  /// YAML i18n file format.
 | 
				
			||||||
  yaml,
 | 
					  yaml,
 | 
				
			||||||
  yml,
 | 
					  yml,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// ARB i18 file format.
 | 
					  /// ARB i18n file format.
 | 
				
			||||||
  arb;
 | 
					  arb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Returns the [Format] that matches the given [ext].
 | 
					  /// Returns the [Format] that matches the given [ext].
 | 
				
			||||||
@ -49,6 +49,7 @@ enum Format {
 | 
				
			|||||||
  static Format? extensionOf(String path) =>
 | 
					  static Format? extensionOf(String path) =>
 | 
				
			||||||
      fromExtension(path.split('.').last);
 | 
					      fromExtension(path.split('.').last);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Returns the [Parser] associated with this [Format].
 | 
				
			||||||
  Parser<String, Map<String, dynamic>> get parser {
 | 
					  Parser<String, Map<String, dynamic>> get parser {
 | 
				
			||||||
    switch (this) {
 | 
					    switch (this) {
 | 
				
			||||||
      case Format.json:
 | 
					      case Format.json:
 | 
				
			||||||
 | 
				
			|||||||
@ -17,9 +17,17 @@
 | 
				
			|||||||
import 'package:wyatt_i18n/src/core/utils/json_parser.dart';
 | 
					import 'package:wyatt_i18n/src/core/utils/json_parser.dart';
 | 
				
			||||||
import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
					import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// {@template arb_parser}
 | 
				
			||||||
 | 
					/// A class that parses a given input of type [String] into a given output
 | 
				
			||||||
 | 
					/// of type [Map<String, dynamic>].
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
class ArbParser extends Parser<String, Map<String, dynamic>> {
 | 
					class ArbParser extends Parser<String, Map<String, dynamic>> {
 | 
				
			||||||
 | 
					  /// {@macro arb_parser}
 | 
				
			||||||
  const ArbParser() : super();
 | 
					  const ArbParser() : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Parses the given [input] of type [String] into a given output of type
 | 
				
			||||||
 | 
					  /// [Map<String, dynamic>].
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
  /// ARB files are JSON files, so we can use the JSON parser.
 | 
					  /// ARB files are JSON files, so we can use the JSON parser.
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Map<String, dynamic> parse(String input) => const JsonParser().parse(input);
 | 
					  Map<String, dynamic> parse(String input) => const JsonParser().parse(input);
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,8 @@ import 'dart:convert';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:flutter/services.dart';
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AssetsUtils {
 | 
					/// A class that contains utility methods for assets.
 | 
				
			||||||
 | 
					abstract class AssetsUtils {
 | 
				
			||||||
  /// Checks if the given [assetPath] is a local asset.
 | 
					  /// Checks if the given [assetPath] is a local asset.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// In fact, this method loads the asset and checks if it is null.
 | 
					  /// In fact, this method loads the asset and checks if it is null.
 | 
				
			||||||
 | 
				
			|||||||
@ -16,17 +16,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:collection/collection.dart';
 | 
					import 'package:collection/collection.dart';
 | 
				
			||||||
import 'package:intl/intl.dart';
 | 
					import 'package:intl/intl.dart';
 | 
				
			||||||
import 'package:wyatt_i18n/src/core/utils/icu_parser.dart';
 | 
					 | 
				
			||||||
import 'package:wyatt_i18n/src/domain/entities/tokens.dart';
 | 
					import 'package:wyatt_i18n/src/domain/entities/tokens.dart';
 | 
				
			||||||
import 'package:wyatt_i18n/wyatt_i18n.dart';
 | 
					import 'package:wyatt_i18n/wyatt_i18n.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class I18nParser extends Parser<String, String> {
 | 
					/// {@template i18n_file_parser}
 | 
				
			||||||
  const I18nParser({
 | 
					/// This class is responsible for parsing the [I18nFile] and returning the
 | 
				
			||||||
 | 
					/// translated string.
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
 | 
					class I18nFileParser extends Parser<String, String> {
 | 
				
			||||||
 | 
					  /// {@macro i18n_file_parser}
 | 
				
			||||||
 | 
					  const I18nFileParser({
 | 
				
			||||||
    required this.i18n,
 | 
					    required this.i18n,
 | 
				
			||||||
    this.arguments = const {},
 | 
					    this.arguments = const {},
 | 
				
			||||||
  }) : super();
 | 
					  }) : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final I18n i18n;
 | 
					  /// The [I18nFile] to be parsed.
 | 
				
			||||||
 | 
					  final I18nFile i18n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The arguments to be used in the translation.
 | 
				
			||||||
  final Map<String, dynamic> arguments;
 | 
					  final Map<String, dynamic> arguments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dynamic getArgument(String key) {
 | 
					  dynamic getArgument(String key) {
 | 
				
			||||||
@ -19,7 +19,13 @@
 | 
				
			|||||||
import 'package:petitparser/petitparser.dart' hide Token;
 | 
					import 'package:petitparser/petitparser.dart' hide Token;
 | 
				
			||||||
import 'package:wyatt_i18n/src/domain/entities/tokens.dart';
 | 
					import 'package:wyatt_i18n/src/domain/entities/tokens.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// {@template icu_parser}
 | 
				
			||||||
 | 
					/// A parser for ICU messages.
 | 
				
			||||||
 | 
					/// See https://unicode-org.github.io/icu/userguide/format_parse/messages/
 | 
				
			||||||
 | 
					/// for the syntax.
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
class IcuParser {
 | 
					class IcuParser {
 | 
				
			||||||
 | 
					  /// {@macro icu_parser}
 | 
				
			||||||
  IcuParser() {
 | 
					  IcuParser() {
 | 
				
			||||||
    // There is a cycle here, so we need the explicit
 | 
					    // There is a cycle here, so we need the explicit
 | 
				
			||||||
    // set to avoid infinite recursion.
 | 
					    // set to avoid infinite recursion.
 | 
				
			||||||
 | 
				
			|||||||
@ -19,9 +19,16 @@ import 'dart:convert';
 | 
				
			|||||||
import 'package:wyatt_i18n/src/core/exceptions/exceptions.dart';
 | 
					import 'package:wyatt_i18n/src/core/exceptions/exceptions.dart';
 | 
				
			||||||
import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
					import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// {@template json_parser}
 | 
				
			||||||
 | 
					/// A class that parses a given input of type [String] into a given output
 | 
				
			||||||
 | 
					/// of type [Map<String, dynamic>].
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
class JsonParser extends Parser<String, Map<String, dynamic>> {
 | 
					class JsonParser extends Parser<String, Map<String, dynamic>> {
 | 
				
			||||||
 | 
					  /// {@macro json_parser}
 | 
				
			||||||
  const JsonParser() : super();
 | 
					  const JsonParser() : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Parses the given [input] of type [String] into a given output of type
 | 
				
			||||||
 | 
					  /// [Map<String, dynamic>].
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Map<String, dynamic> parse(String input) {
 | 
					  Map<String, dynamic> parse(String input) {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,13 @@
 | 
				
			|||||||
// You should have received a copy of the GNU General Public License
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// {@template parser}
 | 
				
			||||||
 | 
					/// A class that parses a given input into a given output.
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
abstract class Parser<I, O> {
 | 
					abstract class Parser<I, O> {
 | 
				
			||||||
 | 
					  /// {@macro parser}
 | 
				
			||||||
  const Parser();
 | 
					  const Parser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Parses the given [input] of type [I] into a given output of type [O].
 | 
				
			||||||
  O parse(I input);
 | 
					  O parse(I input);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@
 | 
				
			|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export 'arb_parser.dart';
 | 
					export 'arb_parser.dart';
 | 
				
			||||||
export 'i18n_parser.dart';
 | 
					export 'i18n_file_parser.dart';
 | 
				
			||||||
export 'icu_parser.dart';
 | 
					export 'icu_parser.dart';
 | 
				
			||||||
export 'json_parser.dart';
 | 
					export 'json_parser.dart';
 | 
				
			||||||
export 'parser.dart';
 | 
					export 'parser.dart';
 | 
				
			||||||
 | 
				
			|||||||
@ -18,9 +18,15 @@ import 'package:wyatt_i18n/src/core/exceptions/exceptions.dart';
 | 
				
			|||||||
import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
					import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
				
			||||||
import 'package:yaml/yaml.dart';
 | 
					import 'package:yaml/yaml.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// {@template yaml_parser}
 | 
				
			||||||
 | 
					/// A class that parses a given YAML input into a given output.
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
class YamlParser extends Parser<String, Map<String, dynamic>> {
 | 
					class YamlParser extends Parser<String, Map<String, dynamic>> {
 | 
				
			||||||
 | 
					  /// {@macro yaml_parser}
 | 
				
			||||||
  const YamlParser() : super();
 | 
					  const YamlParser() : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Parses the given [input] of type [String] into a given output of type
 | 
				
			||||||
 | 
					  /// [Map<String, dynamic>].
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Map<String, dynamic> parse(String input) {
 | 
					  Map<String, dynamic> parse(String input) {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
 | 
				
			|||||||
@ -27,20 +27,23 @@ import 'package:wyatt_i18n/src/domain/data_sources/i18n_data_source.dart';
 | 
				
			|||||||
/// The [baseName] is the name of the i18n files without the extension.
 | 
					/// The [baseName] is the name of the i18n files without the extension.
 | 
				
			||||||
/// The [format] is the format of the i18n files.
 | 
					/// The [format] is the format of the i18n files.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// For example, if the i18n files are located in the `assets` and are named
 | 
					/// For example, if the i18n files are located in the `assets/l10n/` and are
 | 
				
			||||||
/// `i18n.en.arb`, `i18n.fr.arb`, etc., then the [basePath] is `assets` and
 | 
					/// named `i18n.en.arb`, `i18n.fr.arb`, etc., then the [basePath]
 | 
				
			||||||
/// the [baseName] is `i18n` and the [format] is [Format.arb].
 | 
					/// is `l10n` and the [baseName] is `i18n` and the [format] is [Format.arb].
 | 
				
			||||||
/// {@endtemplate}
 | 
					/// {@endtemplate}
 | 
				
			||||||
class AssetsFileDataSourceImpl extends I18nDataSource {
 | 
					class AssetsFileDataSourceImpl extends I18nDataSource {
 | 
				
			||||||
  /// {@macro assets_file_data_source_impl}
 | 
					  /// {@macro assets_file_data_source_impl}
 | 
				
			||||||
  AssetsFileDataSourceImpl({
 | 
					  AssetsFileDataSourceImpl({
 | 
				
			||||||
    this.basePath = 'assets',
 | 
					    this.basePath = '',
 | 
				
			||||||
    this.baseName = 'i18n',
 | 
					    this.baseName = 'i18n',
 | 
				
			||||||
    super.format = Format.arb,
 | 
					    super.format = Format.arb,
 | 
				
			||||||
    super.defaultLocale = 'en',
 | 
					    super.defaultLocale = 'en',
 | 
				
			||||||
  }) : super();
 | 
					  }) : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The folder where the i18n files are located.
 | 
					  /// The folder where the i18n files are located.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Note: The path is relative to the `assets` folder. So, `assets/l10n/`
 | 
				
			||||||
 | 
					  /// is `l10n`.
 | 
				
			||||||
  final String basePath;
 | 
					  final String basePath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The name of the i18n files without the extension.
 | 
					  /// The name of the i18n files without the extension.
 | 
				
			||||||
 | 
				
			|||||||
@ -38,16 +38,16 @@ import 'package:wyatt_i18n/src/domain/data_sources/i18n_data_source.dart';
 | 
				
			|||||||
/// then the fallback i18n files are loaded from the [fallbackAssetPath] in
 | 
					/// then the fallback i18n files are loaded from the [fallbackAssetPath] in
 | 
				
			||||||
/// the root bundle.
 | 
					/// the root bundle.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// For example, if the fallback i18n files are located in the `assets` and are
 | 
					/// For example, if the fallback i18n files are located in the `assets/l10n/`
 | 
				
			||||||
/// named `i18n.arb`, `i18n.en.arb`, `i18n.fr.arb`, etc., then the
 | 
					/// and are named `i18n.arb`, `i18n.en.arb`, `i18n.fr.arb`, etc., then the
 | 
				
			||||||
/// [fallbackAssetPath] is `assets`.
 | 
					/// [fallbackAssetPath] is `l10n`.
 | 
				
			||||||
/// {@endtemplate}
 | 
					/// {@endtemplate}
 | 
				
			||||||
class NetworkDataSourceImpl extends I18nDataSource {
 | 
					class NetworkDataSourceImpl extends I18nDataSource {
 | 
				
			||||||
  /// {@macro network_data_source_impl}
 | 
					  /// {@macro network_data_source_impl}
 | 
				
			||||||
  const NetworkDataSourceImpl({
 | 
					  const NetworkDataSourceImpl({
 | 
				
			||||||
    required this.baseUri,
 | 
					    required this.baseUri,
 | 
				
			||||||
    this.baseName = 'i18n',
 | 
					    this.baseName = 'i18n',
 | 
				
			||||||
    this.fallbackAssetPath = 'assets',
 | 
					    this.fallbackAssetPath = '',
 | 
				
			||||||
    super.format = Format.arb,
 | 
					    super.format = Format.arb,
 | 
				
			||||||
    super.defaultLocale = 'en',
 | 
					    super.defaultLocale = 'en',
 | 
				
			||||||
  }) : super();
 | 
					  }) : super();
 | 
				
			||||||
@ -62,6 +62,9 @@ class NetworkDataSourceImpl extends I18nDataSource {
 | 
				
			|||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// This is used when the i18n file for the given locale is not found or
 | 
					  /// This is used when the i18n file for the given locale is not found or
 | 
				
			||||||
  /// if the fetch fails.
 | 
					  /// if the fetch fails.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Note: The path is relative to the root bundle. So `assets/l10n/` is
 | 
				
			||||||
 | 
					  /// `l10n`.
 | 
				
			||||||
  final String fallbackAssetPath;
 | 
					  final String fallbackAssetPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Tries to load the i18n file from the given [locale].
 | 
					  /// Tries to load the i18n file from the given [locale].
 | 
				
			||||||
@ -122,9 +125,17 @@ class NetworkDataSourceImpl extends I18nDataSource {
 | 
				
			|||||||
    return content;
 | 
					    return content;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Loads the i18n file for the given [locale].
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// If the [locale] is null, then the default i18n file is loaded from the
 | 
				
			||||||
 | 
					  /// fallback asset path.
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Future<String> load({required String? locale}) async => _tryLoad(locale);
 | 
					  Future<String> load({required String? locale}) async => _tryLoad(locale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Loads the i18n file from the given [uri].
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// If the fetch fails, then the fallback i18n files are loaded from the
 | 
				
			||||||
 | 
					  /// [fallbackAssetPath] in the root bundle.
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Future<String> loadFrom(Uri uri) async => _tryLoad(null, overrideUri: uri);
 | 
					  Future<String> loadFrom(Uri uri) async => _tryLoad(null, overrideUri: uri);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -31,12 +31,12 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
  final I18nDataSource dataSource;
 | 
					  final I18nDataSource dataSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The current i18n instance.
 | 
					  /// The current i18n instance.
 | 
				
			||||||
  I18n _i18n = const I18n.empty();
 | 
					  I18nFile _i18n = const I18nFile.empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  I18n get i18n => _i18n;
 | 
					  I18nFile get i18n => _i18n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<I18n> _parse(
 | 
					  Future<I18nFile> _parse(
 | 
				
			||||||
    String content,
 | 
					    String content,
 | 
				
			||||||
    Parser<String, Map<String, dynamic>> parser, {
 | 
					    Parser<String, Map<String, dynamic>> parser, {
 | 
				
			||||||
    String? locale,
 | 
					    String? locale,
 | 
				
			||||||
@ -75,7 +75,7 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return I18n(
 | 
					    return I18nFile(
 | 
				
			||||||
      locale: parsedLocale,
 | 
					      locale: parsedLocale,
 | 
				
			||||||
      unparsedData: content,
 | 
					      unparsedData: content,
 | 
				
			||||||
      data: parsed,
 | 
					      data: parsed,
 | 
				
			||||||
@ -83,12 +83,12 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<I18n> load({
 | 
					  FutureOrResult<I18nFile> load({
 | 
				
			||||||
    required String? locale,
 | 
					    required String? locale,
 | 
				
			||||||
    bool strict = false,
 | 
					    bool strict = false,
 | 
				
			||||||
    Parser<String, Map<String, dynamic>>? parser,
 | 
					    Parser<String, Map<String, dynamic>>? parser,
 | 
				
			||||||
  }) async =>
 | 
					  }) async =>
 | 
				
			||||||
      await Result.tryCatchAsync<I18n, AppException, AppException>(
 | 
					      await Result.tryCatchAsync<I18nFile, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final content = await dataSource.load(locale: locale);
 | 
					          final content = await dataSource.load(locale: locale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -103,11 +103,11 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  FutureOrResult<I18n> loadFrom(
 | 
					  FutureOrResult<I18nFile> loadFrom(
 | 
				
			||||||
    Uri uri, {
 | 
					    Uri uri, {
 | 
				
			||||||
    Parser<String, Map<String, dynamic>>? parser,
 | 
					    Parser<String, Map<String, dynamic>>? parser,
 | 
				
			||||||
  }) async =>
 | 
					  }) async =>
 | 
				
			||||||
      await Result.tryCatchAsync<I18n, AppException, AppException>(
 | 
					      await Result.tryCatchAsync<I18nFile, AppException, AppException>(
 | 
				
			||||||
        () async {
 | 
					        () async {
 | 
				
			||||||
          final content = await dataSource.loadFrom(uri);
 | 
					          final content = await dataSource.loadFrom(uri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -127,7 +127,8 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
    String key, [
 | 
					    String key, [
 | 
				
			||||||
    Map<String, dynamic> arguments = const {},
 | 
					    Map<String, dynamic> arguments = const {},
 | 
				
			||||||
  ]) {
 | 
					  ]) {
 | 
				
			||||||
    final I18nParser parser = I18nParser(i18n: _i18n, arguments: arguments);
 | 
					    final I18nFileParser parser =
 | 
				
			||||||
 | 
					        I18nFileParser(i18n: _i18n, arguments: arguments);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_i18n.containsKey(key)) {
 | 
					    if (_i18n.containsKey(key)) {
 | 
				
			||||||
      return Result.tryCatch<String, AppException, AppException>(
 | 
					      return Result.tryCatch<String, AppException, AppException>(
 | 
				
			||||||
@ -140,7 +141,7 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Result<I18n, AppException> getI18n() =>
 | 
					  Result<I18nFile, AppException> getI18n() =>
 | 
				
			||||||
      Result.conditional(!_i18n.isEmpty, _i18n, NotLoadedException());
 | 
					      Result.conditional(!_i18n.isEmpty, _i18n, NotLoadedException());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
@ -148,7 +149,7 @@ class I18nRepositoryImpl extends I18nRepository {
 | 
				
			|||||||
      Result.conditional(!_i18n.isEmpty, _i18n.locale, NotLoadedException());
 | 
					      Result.conditional(!_i18n.isEmpty, _i18n.locale, NotLoadedException());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Result<void, AppException> setI18n(I18n i18n) {
 | 
					  Result<void, AppException> setI18n(I18nFile i18n) {
 | 
				
			||||||
    _i18n = i18n;
 | 
					    _i18n = i18n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return const Ok(null);
 | 
					    return const Ok(null);
 | 
				
			||||||
 | 
				
			|||||||
@ -16,4 +16,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export 'data_sources/i18n_data_source.dart';
 | 
					export 'data_sources/i18n_data_source.dart';
 | 
				
			||||||
export 'entities/i18n.dart';
 | 
					export 'entities/i18n.dart';
 | 
				
			||||||
 | 
					export 'entities/i18n_file.dart';
 | 
				
			||||||
export 'repositories/i18n_repository.dart';
 | 
					export 'repositories/i18n_repository.dart';
 | 
				
			||||||
 | 
				
			|||||||
@ -15,30 +15,46 @@
 | 
				
			|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
					import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_i18n/wyatt_i18n.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Data structure for i18n files.
 | 
					/// {@template i18n}
 | 
				
			||||||
 | 
					/// This class is used to store the translations of the application.
 | 
				
			||||||
 | 
					/// This entity is used by the I18nDelegate and Flutter's Localizations
 | 
				
			||||||
 | 
					/// widget to provide the translations to the application.
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
class I18n extends Entity {
 | 
					class I18n extends Entity {
 | 
				
			||||||
  const I18n({
 | 
					  /// {@macro i18n}
 | 
				
			||||||
    required this.locale,
 | 
					  I18n({
 | 
				
			||||||
    required this.unparsedData,
 | 
					    required this.i18nRepository,
 | 
				
			||||||
    required this.data,
 | 
					 | 
				
			||||||
  }) : super();
 | 
					  }) : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Creates an empty i18n file.
 | 
					  final I18nRepository i18nRepository;
 | 
				
			||||||
  const I18n.empty() : this(locale: '', unparsedData: '', data: const {});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The locale of the i18n file.
 | 
					  /// Get the translation of the given [key].
 | 
				
			||||||
  final String locale;
 | 
					  /// If the [key] is not found, the [key] itself is returned.
 | 
				
			||||||
 | 
					  /// If the [key] is found, the translation is returned.
 | 
				
			||||||
 | 
					  /// If [args] is not null, the translation is formatted with the
 | 
				
			||||||
 | 
					  /// given arguments.
 | 
				
			||||||
 | 
					  String get(String key, [Map<String, dynamic>? args]) {
 | 
				
			||||||
 | 
					    final result = i18nRepository.get(key, args ?? const <String, dynamic>{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The unparsed data of the i18n file.
 | 
					    return result.fold(
 | 
				
			||||||
  final String unparsedData;
 | 
					      (value) => value,
 | 
				
			||||||
 | 
					      (error) => key,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The data of the i18n file.
 | 
					  /// Get the translation of the given [key].
 | 
				
			||||||
  final Map<String, dynamic> data;
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Note: arguments are not supported.
 | 
				
			||||||
 | 
					  String operator [](String key) => get(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool containsKey(String key) => data.containsKey(key);
 | 
					  /// Get the translation of the given [key].
 | 
				
			||||||
 | 
					  String call(String key, [Map<String, dynamic>? args]) => get(key, args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dynamic operator [](String key) => data[key];
 | 
					  /// Load the translations from the given [locale].
 | 
				
			||||||
 | 
					  /// If the [locale] is not found, the default locale is loaded.
 | 
				
			||||||
  bool get isEmpty => data.isEmpty && unparsedData.isEmpty && locale.isEmpty;
 | 
					  Future<void> load(String locale) async {
 | 
				
			||||||
 | 
					    await i18nRepository.load(locale: locale);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										54
									
								
								packages/wyatt_i18n/lib/src/domain/entities/i18n_file.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								packages/wyatt_i18n/lib/src/domain/entities/i18n_file.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2023 WYATT GROUP
 | 
				
			||||||
 | 
					// Please see the AUTHORS file for details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:equatable/equatable.dart';
 | 
				
			||||||
 | 
					import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// {@template i18n_file}
 | 
				
			||||||
 | 
					/// Data structure for i18n files.
 | 
				
			||||||
 | 
					/// {@endtemplate}
 | 
				
			||||||
 | 
					class I18nFile extends Entity with EquatableMixin {
 | 
				
			||||||
 | 
					  /// {@macro i18n_file}
 | 
				
			||||||
 | 
					  const I18nFile({
 | 
				
			||||||
 | 
					    required this.locale,
 | 
				
			||||||
 | 
					    required this.unparsedData,
 | 
				
			||||||
 | 
					    required this.data,
 | 
				
			||||||
 | 
					  }) : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Creates an empty i18n file.
 | 
				
			||||||
 | 
					  const I18nFile.empty() : this(locale: '', unparsedData: '', data: const {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The locale of the i18n file.
 | 
				
			||||||
 | 
					  final String locale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The unparsed data of the i18n file.
 | 
				
			||||||
 | 
					  final String unparsedData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The data of the i18n file.
 | 
				
			||||||
 | 
					  final Map<String, dynamic> data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Checks if the i18n file contains a key.
 | 
				
			||||||
 | 
					  bool containsKey(String key) => data.containsKey(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Gets the value of a key.
 | 
				
			||||||
 | 
					  dynamic operator [](String key) => data[key];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Checks if the i18n file is empty.
 | 
				
			||||||
 | 
					  bool get isEmpty => data.isEmpty && unparsedData.isEmpty && locale.isEmpty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  List<Object?> get props => [locale, unparsedData, data];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,7 +16,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
					import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
				
			||||||
import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
					import 'package:wyatt_i18n/src/core/utils/parser.dart';
 | 
				
			||||||
import 'package:wyatt_i18n/src/domain/entities/i18n.dart';
 | 
					import 'package:wyatt_i18n/src/domain/entities/i18n_file.dart';
 | 
				
			||||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
 | 
					import 'package:wyatt_type_utils/wyatt_type_utils.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// {@template i18n_repository}
 | 
					/// {@template i18n_repository}
 | 
				
			||||||
@ -29,7 +29,7 @@ abstract class I18nRepository extends BaseRepository {
 | 
				
			|||||||
  const I18nRepository() : super();
 | 
					  const I18nRepository() : super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// The current i18n file.
 | 
					  /// The current i18n file.
 | 
				
			||||||
  I18n get i18n;
 | 
					  I18nFile get i18n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Loads the i18n file from the source.
 | 
					  /// Loads the i18n file from the source.
 | 
				
			||||||
  /// If [strict] is `true`, it will throw an NoLocaleException if the
 | 
					  /// If [strict] is `true`, it will throw an NoLocaleException if the
 | 
				
			||||||
@ -37,7 +37,7 @@ abstract class I18nRepository extends BaseRepository {
 | 
				
			|||||||
  /// set the locale to the given [locale].
 | 
					  /// set the locale to the given [locale].
 | 
				
			||||||
  /// If [parser] is not `null`, it will use the given parser to parse
 | 
					  /// If [parser] is not `null`, it will use the given parser to parse
 | 
				
			||||||
  /// the i18n file. Otherwise, it will use the default parser for the format.
 | 
					  /// the i18n file. Otherwise, it will use the default parser for the format.
 | 
				
			||||||
  FutureOrResult<I18n> load({
 | 
					  FutureOrResult<I18nFile> load({
 | 
				
			||||||
    required String? locale,
 | 
					    required String? locale,
 | 
				
			||||||
    bool strict = false,
 | 
					    bool strict = false,
 | 
				
			||||||
    Parser<String, Map<String, dynamic>>? parser,
 | 
					    Parser<String, Map<String, dynamic>>? parser,
 | 
				
			||||||
@ -46,7 +46,7 @@ abstract class I18nRepository extends BaseRepository {
 | 
				
			|||||||
  /// Loads the i18n file from the given [uri].
 | 
					  /// Loads the i18n file from the given [uri].
 | 
				
			||||||
  /// If [parser] is not `null`, it will use the given parser to parse
 | 
					  /// If [parser] is not `null`, it will use the given parser to parse
 | 
				
			||||||
  /// the i18n file. Otherwise, it will use the default parser for the format.
 | 
					  /// the i18n file. Otherwise, it will use the default parser for the format.
 | 
				
			||||||
  FutureOrResult<I18n> loadFrom(
 | 
					  FutureOrResult<I18nFile> loadFrom(
 | 
				
			||||||
    Uri uri, {
 | 
					    Uri uri, {
 | 
				
			||||||
    Parser<String, Map<String, dynamic>>? parser,
 | 
					    Parser<String, Map<String, dynamic>>? parser,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
@ -63,12 +63,12 @@ abstract class I18nRepository extends BaseRepository {
 | 
				
			|||||||
  /// Sets the current i18n instance.
 | 
					  /// Sets the current i18n instance.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// This method is used to set the current i18n instance.
 | 
					  /// This method is used to set the current i18n instance.
 | 
				
			||||||
  Result<void, AppException> setI18n(I18n i18n);
 | 
					  Result<void, AppException> setI18n(I18nFile i18n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Gets the current i18n instance.
 | 
					  /// Gets the current i18n instance.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// This method is used to get the current i18n instance.
 | 
					  /// This method is used to get the current i18n instance.
 | 
				
			||||||
  Result<I18n, AppException> getI18n();
 | 
					  Result<I18nFile, AppException> getI18n();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Gets the current locale.
 | 
					  /// Gets the current locale.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +0,0 @@
 | 
				
			|||||||
// Copyright (C) 2023 WYATT GROUP
 | 
					 | 
				
			||||||
// Please see the AUTHORS file for details.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This program is free software: you can redistribute it and/or modify
 | 
					 | 
				
			||||||
// it under the terms of the GNU General Public License as published by
 | 
					 | 
				
			||||||
// the Free Software Foundation, either version 3 of the License, or
 | 
					 | 
				
			||||||
// any later version.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// This program is distributed in the hope that it will be useful,
 | 
					 | 
				
			||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					 | 
				
			||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
					 | 
				
			||||||
// GNU General Public License for more details.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// You should have received a copy of the GNU General Public License
 | 
					 | 
				
			||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
abstract class WyattI18n {
 | 
					 | 
				
			||||||
  static String get testString => 'Package: Wyatt I18n';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -14,7 +14,9 @@
 | 
				
			|||||||
// You should have received a copy of the GNU General Public License
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
					// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// A package by wyatt studio
 | 
					/// This package aims to facilitate and improve the internationalization of
 | 
				
			||||||
 | 
					/// your applications. It allows, among other things, to load translation
 | 
				
			||||||
 | 
					/// files on the fly during the execution of the application.
 | 
				
			||||||
library wyatt_i18n;
 | 
					library wyatt_i18n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export 'src/src.dart';
 | 
					export 'src/src.dart';
 | 
				
			||||||
 | 
				
			|||||||
@ -8,9 +8,12 @@ environment:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
dependencies:
 | 
					dependencies:
 | 
				
			||||||
  collection: ^1.17.0
 | 
					  collection: ^1.17.0
 | 
				
			||||||
 | 
					  equatable: ^2.0.5
 | 
				
			||||||
  flutter: {sdk: flutter}
 | 
					  flutter: {sdk: flutter}
 | 
				
			||||||
 | 
					  flutter_bloc: ^8.1.2
 | 
				
			||||||
 | 
					  flutter_localizations: {sdk: flutter}
 | 
				
			||||||
  http: ^0.13.5
 | 
					  http: ^0.13.5
 | 
				
			||||||
  intl: ^0.18.0
 | 
					  intl: ^0.17.0
 | 
				
			||||||
  path: ^1.8.0
 | 
					  path: ^1.8.0
 | 
				
			||||||
  petitparser: ^5.1.0
 | 
					  petitparser: ^5.1.0
 | 
				
			||||||
  wyatt_architecture:
 | 
					  wyatt_architecture:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user