diff --git a/lib/src/generator/l10n_dart_generator.dart b/lib/src/generator/l10n_dart_generator.dart index 0e008e4..ef0eb65 100644 --- a/lib/src/generator/l10n_dart_generator.dart +++ b/lib/src/generator/l10n_dart_generator.dart @@ -1,3 +1,6 @@ +import 'package:arbify/src/language_identifier_parser/locale.dart'; +import 'package:arbify/src/language_identifier_parser/locale_parser.dart'; + import '../icu_parser/icu_parser.dart'; import '../arb_parser/arb_file.dart'; @@ -5,7 +8,6 @@ class L10nDartGenerator { const L10nDartGenerator(); String generate(ArbFile template, List locales) { - final localeItems = locales.map((locale) => "\n '$locale',").join(); final messagesBuilder = StringBuffer(); template.messages.forEach((message) { @@ -50,6 +52,13 @@ class L10nDartGenerator { final messages = messagesBuilder.toString(); + final parsedLocales = locales + .map((locale) => LanguageIdentifierParser().parse(locale)) + .toList(); + final supportedLocales = _generateSupportedLocalesArray(parsedLocales); + final localeItems = + parsedLocales.map((locale) => "\n '${locale.language}',").join(); + return """// File generated with arbify_flutter. // DO NOT MODIFY BY HAND. // ignore_for_file: lines_longer_than_80_chars, non_constant_identifier_names @@ -82,6 +91,9 @@ class S { class ArbifyLocalizationsDelegate extends LocalizationsDelegate { const ArbifyLocalizationsDelegate(); + List get supportedLocales => [ +$supportedLocales ]; + @override bool isSupported(Locale locale) => [$localeItems ].contains(locale.languageCode); @@ -94,4 +106,21 @@ class ArbifyLocalizationsDelegate extends LocalizationsDelegate { } """; } + + String _generateSupportedLocalesArray(List locales) { + final supportedLocales = StringBuffer(); + + locales.forEach((locale) { + final languageCode = "languageCode: '${locale.language}'"; + final scriptCode = + locale.script == null ? '' : ", scriptCode: '${locale.script}'"; + final countryCode = + locale.region == null ? '' : ", countryCode: '${locale.region}'"; + + supportedLocales.writeln( + ' Locale.fromSubtags($languageCode$scriptCode$countryCode),'); + }); + + return supportedLocales.toString(); + } } diff --git a/lib/src/language_identifier_parser/locale.dart b/lib/src/language_identifier_parser/locale.dart new file mode 100644 index 0000000..163bc46 --- /dev/null +++ b/lib/src/language_identifier_parser/locale.dart @@ -0,0 +1,7 @@ +class Locale { + final String language; + final String script; + final String region; + + Locale({this.language, this.script, this.region}); +} diff --git a/lib/src/language_identifier_parser/locale_parser.dart b/lib/src/language_identifier_parser/locale_parser.dart new file mode 100644 index 0000000..e494fee --- /dev/null +++ b/lib/src/language_identifier_parser/locale_parser.dart @@ -0,0 +1,25 @@ +// https://www.unicode.org/reports/tr35/#Unicode_language_identifier +import 'package:arbify/src/language_identifier_parser/locale.dart'; +import 'package:petitparser/petitparser.dart'; + +class LanguageIdentifierParser { + Parser get alphanum => letter() | digit(); + Parser get sep => char('_') | char('-'); + + Parser get language => + (letter().repeat(2, 3) | letter().repeat(5, 8)).flatten(); + + Parser get script => letter().times(4).flatten(); + Parser get region => (letter().times(2) | digit().times(3)).flatten(); + + Parser get scriptPart => (sep & script).map((value) => value[1]).optional(); + Parser get regionPart => (sep & region).map((value) => value[1]).optional(); + + Parser get id => language & scriptPart & regionPart; + + Locale parse(String text) => id + .map((value) => + Locale(language: value[0], script: value[1], region: value[2])) + .parse(text) + .value; +} diff --git a/test/locale_parser_test.dart b/test/locale_parser_test.dart new file mode 100644 index 0000000..5a1b032 --- /dev/null +++ b/test/locale_parser_test.dart @@ -0,0 +1,39 @@ +import 'package:arbify/src/language_identifier_parser/locale_parser.dart'; +import 'package:test/test.dart'; + +void main() { + test('parses en-US', () { + final locale = LanguageIdentifierParser().parse('en-US'); + expect(locale.language, equals('en')); + expect(locale.script, isNull); + expect(locale.region, equals('US')); + }); + + test('parses en_GB', () { + final locale = LanguageIdentifierParser().parse('en_GB'); + expect(locale.language, equals('en')); + expect(locale.script, isNull); + expect(locale.region, equals('GB')); + }); + + test('parses es-419', () { + final locale = LanguageIdentifierParser().parse('es-419'); + expect(locale.language, equals('es')); + expect(locale.script, isNull); + expect(locale.region, equals('419')); + }); + + test('parses uz-Cyrl', () { + final locale = LanguageIdentifierParser().parse('uz-Cyrl'); + expect(locale.language, equals('uz')); + expect(locale.script, equals('Cyrl')); + expect(locale.region, isNull); + }); + + test('parses zn-Hans-TW', () { + final locale = LanguageIdentifierParser().parse('zn-Hans-TW'); + expect(locale.language, equals('zn')); + expect(locale.script, equals('Hans')); + expect(locale.region, equals('TW')); + }); +}