add i18n package #164
@ -43,14 +43,30 @@ class App extends StatelessWidget {
 | 
			
		||||
                // test
 | 
			
		||||
                const I18nDataSource dataSource = AssetsFileDataSourceImpl();
 | 
			
		||||
 | 
			
		||||
                const I18nRepository repository =
 | 
			
		||||
                    I18RepositoryImpl(dataSource: dataSource);
 | 
			
		||||
                final I18nRepository repository =
 | 
			
		||||
                    I18nRepositoryImpl(dataSource: dataSource);
 | 
			
		||||
 | 
			
		||||
                final test = (await repository.load('en')).ok;
 | 
			
		||||
                final test1 = (await repository.load(locale: 'en')).ok;
 | 
			
		||||
                // final test2 = (await repository.loadFrom(
 | 
			
		||||
                //   Uri.parse('assets/i18n.en.yaml'),
 | 
			
		||||
                //   parser: const YamlParser(),
 | 
			
		||||
                // ))
 | 
			
		||||
                //     .ok;
 | 
			
		||||
 | 
			
		||||
                print(test?.locale);
 | 
			
		||||
                print(test?.data);
 | 
			
		||||
                print(test?.data['btnAddFile']);
 | 
			
		||||
                // print(test1?.locale);
 | 
			
		||||
                // print(test1?.data);
 | 
			
		||||
                // print(test1?.data['btnAddFile']);
 | 
			
		||||
 | 
			
		||||
                final text = repository.get('youHavePushed', {
 | 
			
		||||
                  'count': 8,
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                print(text.ok);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                // print(test2?.locale);
 | 
			
		||||
                // print(test2?.data);
 | 
			
		||||
                // print(test2?.data['btnAddFile']);
 | 
			
		||||
 | 
			
		||||
                return 'test';
 | 
			
		||||
              }),
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								packages/wyatt_i18n/lib/src/core/utils/i18n_parser.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								packages/wyatt_i18n/lib/src/core/utils/i18n_parser.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,135 @@
 | 
			
		||||
// 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:collection/collection.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/wyatt_i18n.dart';
 | 
			
		||||
 | 
			
		||||
class I18nParser extends Parser<String, String> {
 | 
			
		||||
  const I18nParser({
 | 
			
		||||
    required this.i18n,
 | 
			
		||||
    this.arguments = const {},
 | 
			
		||||
  }) : super();
 | 
			
		||||
 | 
			
		||||
  final I18n i18n;
 | 
			
		||||
  final Map<String, dynamic> arguments;
 | 
			
		||||
 | 
			
		||||
  dynamic getArgument(String key) {
 | 
			
		||||
    final arg = arguments[key];
 | 
			
		||||
    if (arg == null) {
 | 
			
		||||
      throw ArgumentsRequiredException(key, 'value');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return arg;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String pluralToString(Plural token) {
 | 
			
		||||
    final List<Option?> options = token.options;
 | 
			
		||||
    final zero =
 | 
			
		||||
        options.firstWhereOrNull((o) => o!.name == 'zero' || o.name == '=0');
 | 
			
		||||
    final one =
 | 
			
		||||
        options.firstWhereOrNull((o) => o!.name == 'one' || o.name == '=1');
 | 
			
		||||
    final two =
 | 
			
		||||
        options.firstWhereOrNull((o) => o!.name == 'two' || o.name == '=2');
 | 
			
		||||
    final few = options.firstWhereOrNull((o) => o!.name == 'few');
 | 
			
		||||
    final many = options.firstWhereOrNull((o) => o!.name == 'many');
 | 
			
		||||
    final other = options.firstWhereOrNull((o) => o!.name == 'other');
 | 
			
		||||
    final zeroStr = zero?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final oneStr = one?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final twoStr = two?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final fewStr = few?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final manyStr = many?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final otherStr = other?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
 | 
			
		||||
    return Intl.plural(
 | 
			
		||||
      getArgument(token.value) as num,
 | 
			
		||||
      zero: zeroStr,
 | 
			
		||||
      two: twoStr,
 | 
			
		||||
      one: oneStr,
 | 
			
		||||
      few: fewStr,
 | 
			
		||||
      other: otherStr,
 | 
			
		||||
      many: manyStr,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String genderToString(Gender token) {
 | 
			
		||||
    final List<Option?> options = token.options;
 | 
			
		||||
    final other = options.firstWhereOrNull((o) => o!.name == 'other');
 | 
			
		||||
    final male = options.firstWhereOrNull((o) => o!.name == 'male');
 | 
			
		||||
    final female = options.firstWhereOrNull((o) => o!.name == 'female');
 | 
			
		||||
    final otherStr = other?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final maleStr = male?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
    final femaleStr = female?.value.map(parsedElementToString).join() ?? '';
 | 
			
		||||
 | 
			
		||||
    return Intl.gender(
 | 
			
		||||
      getArgument(token.value) as String,
 | 
			
		||||
      other: otherStr,
 | 
			
		||||
      female: femaleStr,
 | 
			
		||||
      male: maleStr,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String selectToString(Select token) {
 | 
			
		||||
    final Map<Object, String> cases = {
 | 
			
		||||
      for (var e in token.options.map(
 | 
			
		||||
        (o) => MapEntry(
 | 
			
		||||
          o.name,
 | 
			
		||||
          o.value.map(parsedElementToString).join(),
 | 
			
		||||
        ),
 | 
			
		||||
      ))
 | 
			
		||||
        e.key: e.value,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return Intl.select(
 | 
			
		||||
      getArgument(token.value) as String,
 | 
			
		||||
      cases,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String parsedElementToString(Token token) {
 | 
			
		||||
    switch (token.type) {
 | 
			
		||||
      case TokenType.literal:
 | 
			
		||||
        return token.value;
 | 
			
		||||
      case TokenType.plural:
 | 
			
		||||
        return pluralToString(token as Plural);
 | 
			
		||||
      case TokenType.gender:
 | 
			
		||||
        return genderToString(token as Gender);
 | 
			
		||||
      case TokenType.argument:
 | 
			
		||||
        return getArgument(token.value).toString();
 | 
			
		||||
      case TokenType.select:
 | 
			
		||||
        return selectToString(token as Select);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String parse(String input, {String? key}) {
 | 
			
		||||
    String? result;
 | 
			
		||||
    try {
 | 
			
		||||
      result = IcuParser().parse(input)?.map(parsedElementToString).join();
 | 
			
		||||
      if (result == null) {
 | 
			
		||||
        throw MalformedValueException(key ?? '', input);
 | 
			
		||||
      }
 | 
			
		||||
    } on ArgumentsRequiredException catch (_) {
 | 
			
		||||
      rethrow;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      throw MalformedValueException(key ?? '', input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										173
									
								
								packages/wyatt_i18n/lib/src/core/utils/icu_parser.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								packages/wyatt_i18n/lib/src/core/utils/icu_parser.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,173 @@
 | 
			
		||||
// 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/>.
 | 
			
		||||
 | 
			
		||||
// ignore_for_file: avoid_dynamic_calls, inference_failure_on_untyped_parameter
 | 
			
		||||
 | 
			
		||||
import 'package:petitparser/petitparser.dart' hide Token;
 | 
			
		||||
import 'package:wyatt_i18n/src/domain/entities/tokens.dart';
 | 
			
		||||
 | 
			
		||||
class IcuParser {
 | 
			
		||||
  IcuParser() {
 | 
			
		||||
    // There is a cycle here, so we need the explicit
 | 
			
		||||
    // set to avoid infinite recursion.
 | 
			
		||||
    interiorText.set(contents.plus() | empty);
 | 
			
		||||
  }
 | 
			
		||||
  Parser get openCurly => char('{');
 | 
			
		||||
 | 
			
		||||
  Parser get closeCurly => char('}');
 | 
			
		||||
 | 
			
		||||
  Parser get quotedCurly => (string("'{'") | string("'}'")).map((x) => x[1]);
 | 
			
		||||
 | 
			
		||||
  Parser get icuEscapedText => quotedCurly | twoSingleQuotes;
 | 
			
		||||
 | 
			
		||||
  Parser get curly => openCurly | closeCurly;
 | 
			
		||||
 | 
			
		||||
  Parser get notAllowedInIcuText => curly | char('<');
 | 
			
		||||
 | 
			
		||||
  Parser get icuText => notAllowedInIcuText.neg();
 | 
			
		||||
 | 
			
		||||
  Parser get notAllowedInNormalText => char('{');
 | 
			
		||||
 | 
			
		||||
  Parser get normalText => notAllowedInNormalText.neg();
 | 
			
		||||
 | 
			
		||||
  Parser get messageText =>
 | 
			
		||||
      (icuEscapedText | icuText).plus().flatten().map(Literal.new);
 | 
			
		||||
 | 
			
		||||
  Parser get nonIcuMessageText => normalText.plus().flatten().map(Literal.new);
 | 
			
		||||
 | 
			
		||||
  Parser get twoSingleQuotes => string("''").map((x) => "'");
 | 
			
		||||
 | 
			
		||||
  Parser get number => digit().plus().flatten().trim().map(int.parse);
 | 
			
		||||
 | 
			
		||||
  Parser get id => (letter() & (word() | char('_')).star()).flatten().trim();
 | 
			
		||||
 | 
			
		||||
  Parser get comma => char(',').trim();
 | 
			
		||||
 | 
			
		||||
  /// Given a list of possible keywords, return a rule that accepts any of them.
 | 
			
		||||
  /// e.g., given ["male", "female", "other"], accept any of them.
 | 
			
		||||
  Parser asKeywords(List<String> list) =>
 | 
			
		||||
      list.map(string).cast<Parser>().reduce((a, b) => a | b).flatten().trim();
 | 
			
		||||
 | 
			
		||||
  Parser get pluralKeyword => asKeywords(
 | 
			
		||||
        ['=0', '=1', '=2', 'zero', 'one', 'two', 'few', 'many', 'other'],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Parser get genderKeyword => asKeywords(['female', 'male', 'other']);
 | 
			
		||||
 | 
			
		||||
  SettableParser<dynamic> interiorText = undefined();
 | 
			
		||||
 | 
			
		||||
  Parser get preface => (openCurly & id & comma).map((values) => values[1]);
 | 
			
		||||
 | 
			
		||||
  Parser get pluralLiteral => string('plural');
 | 
			
		||||
 | 
			
		||||
  Parser get pluralClause =>
 | 
			
		||||
      (pluralKeyword & openCurly & interiorText & closeCurly).trim().map(
 | 
			
		||||
            (result) => Option(
 | 
			
		||||
              result[0] as String,
 | 
			
		||||
              List<Token>.from(
 | 
			
		||||
                (result[2] is List ? result[2] as List : [result[2]])
 | 
			
		||||
                    .cast<Token>(),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
  Parser get plural =>
 | 
			
		||||
      preface & pluralLiteral & comma & pluralClause.plus() & closeCurly;
 | 
			
		||||
 | 
			
		||||
  Parser get intlPlural => plural.map(
 | 
			
		||||
        (result) => Plural(
 | 
			
		||||
          result[0] as String,
 | 
			
		||||
          List<Option>.from(result[3] as Iterable<dynamic>),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Parser get selectLiteral => string('select');
 | 
			
		||||
 | 
			
		||||
  Parser get genderClause =>
 | 
			
		||||
      (genderKeyword & openCurly & interiorText & closeCurly).trim().map(
 | 
			
		||||
            (result) => Option(
 | 
			
		||||
              result[0] as String,
 | 
			
		||||
              List<Token>.from(
 | 
			
		||||
                (result[2] is List ? result[2] as List : [result[2]])
 | 
			
		||||
                    .cast<Token>(),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
  Parser get gender =>
 | 
			
		||||
      preface & selectLiteral & comma & genderClause.plus() & closeCurly;
 | 
			
		||||
 | 
			
		||||
  Parser get intlGender => gender.map(
 | 
			
		||||
        (result) => Gender(
 | 
			
		||||
          result[0] as String,
 | 
			
		||||
          List<Option>.from(result[3] as Iterable<dynamic>),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Parser get selectClause =>
 | 
			
		||||
      (id & openCurly & interiorText & closeCurly).trim().map(
 | 
			
		||||
            (result) => Option(
 | 
			
		||||
              result[0] as String,
 | 
			
		||||
              List<Token>.from(
 | 
			
		||||
                (result[2] is List ? result[2] as List : [result[2]])
 | 
			
		||||
                    .cast<Token>(),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
  Parser get generalSelect =>
 | 
			
		||||
      preface & selectLiteral & comma & selectClause.plus() & closeCurly;
 | 
			
		||||
 | 
			
		||||
  Parser get intlSelect => generalSelect.map(
 | 
			
		||||
        (result) => Select(
 | 
			
		||||
          result[0] as String,
 | 
			
		||||
          List<Option>.from(result[3] as Iterable<dynamic>),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Parser get compound => (((parameter | nonIcuMessageText).plus() &
 | 
			
		||||
              pluralOrGenderOrSelect &
 | 
			
		||||
              (pluralOrGenderOrSelect | parameter | nonIcuMessageText).star()) |
 | 
			
		||||
          (pluralOrGenderOrSelect &
 | 
			
		||||
              (pluralOrGenderOrSelect | parameter | nonIcuMessageText).plus()))
 | 
			
		||||
      .map((result) => result.expand((x) => x is List ? x : [x]).toList());
 | 
			
		||||
 | 
			
		||||
  Parser get pluralOrGenderOrSelect => intlPlural | intlGender | intlSelect;
 | 
			
		||||
 | 
			
		||||
  Parser get contents => pluralOrGenderOrSelect | parameter | messageText;
 | 
			
		||||
 | 
			
		||||
  Parser get simpleText =>
 | 
			
		||||
      (nonIcuMessageText | parameter | openCurly).plus().map(
 | 
			
		||||
            (result) => result
 | 
			
		||||
                .map((item) => item is String ? Literal(item) : item)
 | 
			
		||||
                .toList(),
 | 
			
		||||
          );
 | 
			
		||||
 | 
			
		||||
  Parser get empty => epsilon().map((_) => Literal(''));
 | 
			
		||||
 | 
			
		||||
  Parser get parameter => (openCurly & id & closeCurly)
 | 
			
		||||
      .map((result) => Argument(result[1] as String));
 | 
			
		||||
 | 
			
		||||
  List<Token>? parse(String message) {
 | 
			
		||||
    final parsed = (compound | pluralOrGenderOrSelect | simpleText | empty)
 | 
			
		||||
        .map(
 | 
			
		||||
          (result) => List<Token>.from(result is List ? result : [result]),
 | 
			
		||||
        )
 | 
			
		||||
        .parse(message);
 | 
			
		||||
 | 
			
		||||
    return parsed.isSuccess ? parsed.value : null;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -15,6 +15,8 @@
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
export 'arb_parser.dart';
 | 
			
		||||
export 'i18n_parser.dart';
 | 
			
		||||
export 'icu_parser.dart';
 | 
			
		||||
export 'json_parser.dart';
 | 
			
		||||
export 'parser.dart';
 | 
			
		||||
export 'yaml_parser.dart';
 | 
			
		||||
 | 
			
		||||
@ -16,4 +16,4 @@
 | 
			
		||||
 | 
			
		||||
export 'data_sources/assets_file_data_source_impl.dart';
 | 
			
		||||
export 'data_sources/network_data_source_impl.dart';
 | 
			
		||||
export 'repositories/i18_repository_impl.dart';
 | 
			
		||||
export 'repositories/i18n_repository_impl.dart';
 | 
			
		||||
 | 
			
		||||
@ -15,15 +15,17 @@
 | 
			
		||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
 | 
			
		||||
import 'package:wyatt_i18n/src/core/utils/i18n_parser.dart';
 | 
			
		||||
import 'package:wyatt_i18n/wyatt_i18n.dart';
 | 
			
		||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
 | 
			
		||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart' hide Option;
 | 
			
		||||
 | 
			
		||||
class I18RepositoryImpl extends I18nRepository {
 | 
			
		||||
  const I18RepositoryImpl({
 | 
			
		||||
class I18nRepositoryImpl extends I18nRepository {
 | 
			
		||||
  I18nRepositoryImpl({
 | 
			
		||||
    required this.dataSource,
 | 
			
		||||
  }) : super();
 | 
			
		||||
 | 
			
		||||
  final I18nDataSource dataSource;
 | 
			
		||||
  I18n _i18n = const I18n.empty();
 | 
			
		||||
 | 
			
		||||
  Future<I18n> _parse(
 | 
			
		||||
    String content,
 | 
			
		||||
@ -81,7 +83,7 @@ class I18RepositoryImpl extends I18nRepository {
 | 
			
		||||
        () async {
 | 
			
		||||
          final content = await dataSource.load(locale: locale);
 | 
			
		||||
 | 
			
		||||
          return _parse(
 | 
			
		||||
          return _i18n = await _parse(
 | 
			
		||||
            content,
 | 
			
		||||
            parser ?? dataSource.format.parser,
 | 
			
		||||
            locale: locale,
 | 
			
		||||
@ -102,7 +104,7 @@ class I18RepositoryImpl extends I18nRepository {
 | 
			
		||||
 | 
			
		||||
          /// Strict is always true when loading from a uri. Because
 | 
			
		||||
          /// the locale is not given and can't be inferred.
 | 
			
		||||
          return _parse(
 | 
			
		||||
          return _i18n = await _parse(
 | 
			
		||||
            content,
 | 
			
		||||
            parser ?? dataSource.format.parser,
 | 
			
		||||
            strict: true,
 | 
			
		||||
@ -116,7 +118,15 @@ class I18RepositoryImpl extends I18nRepository {
 | 
			
		||||
    String key, [
 | 
			
		||||
    Map<String, dynamic> arguments = const {},
 | 
			
		||||
  ]) {
 | 
			
		||||
    // TODO: implement get
 | 
			
		||||
    throw UnimplementedError();
 | 
			
		||||
    final I18nParser parser = I18nParser(i18n: _i18n, arguments: arguments);
 | 
			
		||||
 | 
			
		||||
    if (_i18n.containsKey(key)) {
 | 
			
		||||
      return Result.tryCatch<String, AppException, AppException>(
 | 
			
		||||
        () => parser.parse(_i18n[key] as String, key: key),
 | 
			
		||||
        (error) => error,
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
      throw KeyNotFoundException(key, arguments);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -24,6 +24,9 @@ class I18n extends Entity {
 | 
			
		||||
    required this.data,
 | 
			
		||||
  }) : super();
 | 
			
		||||
 | 
			
		||||
  /// Creates an empty i18n file.
 | 
			
		||||
  const I18n.empty() : this(locale: '', unparsedData: '', data: const {});
 | 
			
		||||
 | 
			
		||||
  /// The locale of the i18n file.
 | 
			
		||||
  final String locale;
 | 
			
		||||
 | 
			
		||||
@ -33,13 +36,7 @@ class I18n extends Entity {
 | 
			
		||||
  /// The data of the i18n file.
 | 
			
		||||
  final Map<String, dynamic> data;
 | 
			
		||||
 | 
			
		||||
  String operator [](String key) {
 | 
			
		||||
    final value = data[key];
 | 
			
		||||
  bool containsKey(String key) => data.containsKey(key);
 | 
			
		||||
 | 
			
		||||
    if (value is String) {
 | 
			
		||||
      return value;
 | 
			
		||||
    } else {
 | 
			
		||||
      throw Exception('Invalid i18n key: $key');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  dynamic operator [](String key) => data[key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								packages/wyatt_i18n/lib/src/domain/entities/tokens.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								packages/wyatt_i18n/lib/src/domain/entities/tokens.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
// 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/>.
 | 
			
		||||
 | 
			
		||||
enum TokenType { literal, argument, plural, gender, select }
 | 
			
		||||
 | 
			
		||||
class Token {
 | 
			
		||||
  Token(this.type, this.value);
 | 
			
		||||
  TokenType type;
 | 
			
		||||
  String value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Option {
 | 
			
		||||
  Option(this.name, this.value);
 | 
			
		||||
  String name;
 | 
			
		||||
  List<Token> value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Literal extends Token {
 | 
			
		||||
  Literal(String value) : super(TokenType.literal, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Argument extends Token {
 | 
			
		||||
  Argument(String value) : super(TokenType.argument, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Gender extends Token {
 | 
			
		||||
  Gender(String value, this.options) : super(TokenType.gender, value);
 | 
			
		||||
  List<Option> options;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Plural extends Token {
 | 
			
		||||
  Plural(String value, this.options) : super(TokenType.plural, value);
 | 
			
		||||
  List<Option> options;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Select extends Token {
 | 
			
		||||
  Select(String value, this.options) : super(TokenType.select, value);
 | 
			
		||||
  List<Option> options;
 | 
			
		||||
}
 | 
			
		||||
@ -7,7 +7,9 @@ environment:
 | 
			
		||||
  sdk: ">=2.19.0 <3.0.0"
 | 
			
		||||
 | 
			
		||||
dependencies:
 | 
			
		||||
  collection: ^1.17.0
 | 
			
		||||
  flutter: {sdk: flutter}
 | 
			
		||||
  intl: ^0.18.0
 | 
			
		||||
  path: ^1.8.0
 | 
			
		||||
  petitparser: ^5.1.0
 | 
			
		||||
  wyatt_architecture:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user