Skip to content

Commit

Permalink
Merge pull request #7 from Pavel-Sulimau/feature/supported-locales-pr…
Browse files Browse the repository at this point in the history
…operty

Add 'supportedLocales' property
  • Loading branch information
Tienisto authored Mar 2, 2021
2 parents 51e2bfc + 6dbe3fa commit 267dc12
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 88 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.3.0

- Add `supportedLocales` property that can be used to fill `MaterialApp`'s `supportedLocales` argument.

## 2.2.1

- Fix compilation error occurring when non-standard name (not 'strings.i18n.json') is used for json files.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Lightweight i18n solution. Use JSON files to create typesafe translations.

```yaml
dependencies:
fast_i18n: ^2.2.1
fast_i18n: ^2.3.0

dev_dependencies:
build_runner: any
Expand Down
15 changes: 14 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

```yaml
dependencies:
fast_i18n: ^2.2.1
fast_i18n: ^2.3.0

dev_dependencies:
build_runner: any
Expand Down Expand Up @@ -67,6 +67,19 @@ void initState() {
}
```

## Step 4a: Override 'supportedLocales'

```dart
MaterialApp(
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: LocaleSettings.supportedLocales, // <---
)
```

## Step 4b: iOS-only

```
Expand Down
54 changes: 29 additions & 25 deletions lib/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,27 @@ class I18nBuilder implements Builder {

bool _generated = false;

String get inputFilePattern => options.config['input_file_pattern'] ?? defaultInputFilePattern;
String get outputFilePattern => options.config['output_file_pattern'] ?? defaultOutputFilePattern;
String get inputFilePattern =>
options.config['input_file_pattern'] ?? defaultInputFilePattern;
String get outputFilePattern =>
options.config['output_file_pattern'] ?? defaultOutputFilePattern;

@override
FutureOr<void> build(BuildStep buildStep) async {
final String baseLocale = Utils.normalize(options.config['base_locale'] ?? defaultBaseLocale);
final String baseLocale =
Utils.normalize(options.config['base_locale'] ?? defaultBaseLocale);
final String inputDirectory = options.config['input_directory'];
final String outputDirectory = options.config['output_directory'];
final String translateVar = options.config['output_translate_var'] ?? defaultTranslateVar;
final String translateVar =
options.config['output_translate_var'] ?? defaultTranslateVar;
final String keyCase = options.config['key_case'];
final List<String> maps = options.config['maps']?.cast<String>() ?? [];

if (inputDirectory != null && !buildStep.inputId.path.contains(inputDirectory))
return;
if (inputDirectory != null &&
!buildStep.inputId.path.contains(inputDirectory)) return;

// only generate once
if (_generated)
return;
if (_generated) return;

_generated = true;

Expand All @@ -53,7 +56,8 @@ class I18nBuilder implements Builder {
: Glob('**$inputFilePattern');

await buildStep.findAssets(findAssetsPattern).forEach((assetId) {
final fileNameNoExtension = assetId.pathSegments.last.replaceAll(inputFilePattern, '');
final fileNameNoExtension =
assetId.pathSegments.last.replaceAll(inputFilePattern, '');
final match = Utils.localeRegex.firstMatch(fileNameNoExtension);

if (match != null) {
Expand All @@ -77,12 +81,11 @@ class I18nBuilder implements Builder {

// build config which applies to all locales
final config = I18nConfig(
baseName: baseName ?? defaultBaseName,
baseLocale: baseLocale,
maps: maps,
keyCase: keyCase,
translateVariable: translateVar
);
baseName: baseName ?? defaultBaseName,
baseLocale: baseLocale,
maps: maps,
keyCase: keyCase,
translateVariable: translateVar);

// map each assetId to I18nData
final localesWithData = Map<AssetId, I18nData>();
Expand All @@ -96,23 +99,24 @@ class I18nBuilder implements Builder {

// generate
final String output = generate(
config: config,
translations: localesWithData.values.toList()..sort((a, b) => a.locale.compareTo(b.locale))
);
config: config,
translations: localesWithData.values.toList()
..sort((a, b) => a.locale.compareTo(b.locale)));

// write only to main locale
final AssetId baseId = localesWithData.entries
.firstWhere((element) => element.value.base)
.key;
final AssetId baseId =
localesWithData.entries.firstWhere((element) => element.value.base).key;

final finalOutputDirectory = outputDirectory ?? (baseId.pathSegments..removeLast()).join('/');
final String outFilePath = '$finalOutputDirectory/$baseName$outputFilePattern';
final finalOutputDirectory =
outputDirectory ?? (baseId.pathSegments..removeLast()).join('/');
final String outFilePath =
'$finalOutputDirectory/$baseName$outputFilePattern';

File(outFilePath).writeAsStringSync(output);
}

@override
get buildExtensions => {
inputFilePattern: [outputFilePattern],
};
inputFilePattern: [outputFilePattern],
};
}
53 changes: 45 additions & 8 deletions lib/fast_i18n.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
library fast_i18n;

import 'dart:io';
import 'dart:ui';

import 'package:fast_i18n/utils.dart';

class FastI18n {
static const _localePartsDelimiter = '-';

/// returns the locale string used by the device
static String getDeviceLocale() {
return Platform.localeName;
}
/// Returns the locale string used by the device.
static String getDeviceLocale() => Platform.localeName;

/// returns the candidate (or part of it) if it is supported
/// fallback to base locale
static String selectLocale(String candidate, List<String> supported, String baseLocale) {
/// Returns the candidate (or part of it) if it is supported.
/// Fallbacks to base locale.
static String selectLocale(
String candidate, List<String> supported, String baseLocale) {
// normalize
candidate = Utils.normalize(candidate);

Expand All @@ -23,7 +24,7 @@ class FastI18n {
if (selected != null) return selected;

// 2nd try: match the first part (language)
List<String> deviceLocaleParts = candidate.split('-');
List<String> deviceLocaleParts = candidate.split(_localePartsDelimiter);
selected = supported.firstWhere(
(element) => element == deviceLocaleParts.first,
orElse: () => null);
Expand All @@ -38,4 +39,40 @@ class FastI18n {
// fallback: default locale
return baseLocale;
}

/// Converts the passed locales from [String] to [Locale].
/// Puts the [baseLocale] into the the beginning of the list.
static List<Locale> convertToLocales(
List<String> locales, String baseLocale) {
final rawSupportedLocales = [
baseLocale,
...locales.where((locale) => locale != baseLocale),
];

final supportedLocales = rawSupportedLocales.map((rawLocale) {
if (rawLocale.contains(_localePartsDelimiter)) {
final localeParts = rawLocale
.split(_localePartsDelimiter)
.where((part) => part.isNotEmpty)
.toList();
if (localeParts.length == 2) {
return Locale.fromSubtags(
languageCode: localeParts[0], countryCode: localeParts[1]);
} else if (localeParts.length == 3) {
return Locale.fromSubtags(
languageCode: localeParts[0],
scriptCode: localeParts[1],
countryCode: localeParts[2],
);
} else {
throw Exception(
"The locale '$rawLocale' is not in a supported format. Examples of the supported formats: 'en', 'en-US', 'zh-Hans-CN'.");
}
} else {
return Locale.fromSubtags(languageCode: rawLocale);
}
}).toList();

return supportedLocales;
}
}
Loading

0 comments on commit 267dc12

Please sign in to comment.