feat(i18n): add default locale
This commit is contained in:
parent
cbbde8db85
commit
17ece11170
40
packages/wyatt_i18n/lib/src/core/utils/assets_utils.dart
Normal file
40
packages/wyatt_i18n/lib/src/core/utils/assets_utils.dart
Normal file
@ -0,0 +1,40 @@
|
||||
// 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 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class AssetsUtils {
|
||||
/// Checks if the given [assetPath] is a local asset.
|
||||
///
|
||||
/// In fact, this method loads the asset and checks if it is null.
|
||||
static Future<bool> assetExists(String assetPath) async {
|
||||
final encoded = utf8.encoder.convert(
|
||||
Uri(path: Uri.encodeFull(assetPath)).path,
|
||||
);
|
||||
final asset = await ServicesBinding.instance.defaultBinaryMessenger
|
||||
.send('flutter/assets', encoded.buffer.asByteData());
|
||||
|
||||
return asset != null;
|
||||
}
|
||||
|
||||
/// Cleans the given [path] by removing all the consecutive slashes.
|
||||
/// For example, `///a///b///c///` becomes `/a/b/c/`.
|
||||
/// It also removes the first slash if it exists.
|
||||
static String cleanPath(String path) =>
|
||||
path.replaceAll(RegExp(r'\/+'), '/').replaceFirst(RegExp(r'^\/'), '');
|
||||
}
|
@ -14,11 +14,10 @@
|
||||
// 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 'dart:convert';
|
||||
|
||||
import 'package:flutter/services.dart' show ServicesBinding, rootBundle;
|
||||
import 'package:flutter/services.dart' show AssetBundle, rootBundle;
|
||||
import 'package:wyatt_i18n/src/core/enums/format.dart';
|
||||
import 'package:wyatt_i18n/src/core/exceptions/exceptions.dart';
|
||||
import 'package:wyatt_i18n/src/core/utils/assets_utils.dart';
|
||||
import 'package:wyatt_i18n/src/domain/data_sources/i18n_data_source.dart';
|
||||
|
||||
/// {@template assets_file_data_source_impl}
|
||||
@ -34,10 +33,11 @@ import 'package:wyatt_i18n/src/domain/data_sources/i18n_data_source.dart';
|
||||
/// {@endtemplate}
|
||||
class AssetsFileDataSourceImpl extends I18nDataSource {
|
||||
/// {@macro assets_file_data_source_impl}
|
||||
const AssetsFileDataSourceImpl({
|
||||
AssetsFileDataSourceImpl({
|
||||
this.basePath = 'assets',
|
||||
this.baseName = 'i18n',
|
||||
super.format = Format.arb,
|
||||
super.defaultLocale = 'en',
|
||||
}) : super();
|
||||
|
||||
/// The folder where the i18n files are located.
|
||||
@ -46,29 +46,23 @@ class AssetsFileDataSourceImpl extends I18nDataSource {
|
||||
/// The name of the i18n files without the extension.
|
||||
final String baseName;
|
||||
|
||||
/// Checks if the given [assetPath] is a local asset.
|
||||
///
|
||||
/// In fact, this method loads the asset and checks if it is null.
|
||||
Future<bool> assetExists(String assetPath) async {
|
||||
final encoded = utf8.encoder.convert(
|
||||
Uri(path: Uri.encodeFull(assetPath)).path,
|
||||
);
|
||||
final asset = await ServicesBinding.instance.defaultBinaryMessenger
|
||||
.send('flutter/assets', encoded.buffer.asByteData());
|
||||
|
||||
return asset != null;
|
||||
}
|
||||
/// The asset bundle used to load the i18n files.
|
||||
final AssetBundle assetBundle = rootBundle;
|
||||
|
||||
/// Tries to load the i18n file from the given [locale].
|
||||
Future<String> _tryLoad(String? locale) async {
|
||||
String? content;
|
||||
final ext = format.name;
|
||||
final path = locale == null
|
||||
? '$basePath/$baseName.$ext'
|
||||
: '$basePath/$baseName.$locale.$ext';
|
||||
|
||||
final path = AssetsUtils.cleanPath(
|
||||
locale == null
|
||||
? '$basePath/$baseName.$defaultLocale.$ext'
|
||||
: '$basePath/$baseName.$locale.$ext',
|
||||
);
|
||||
|
||||
try {
|
||||
if (await assetExists(path)) {
|
||||
content = await rootBundle.loadString(path);
|
||||
if (await AssetsUtils.assetExists(path)) {
|
||||
content = await assetBundle.loadString(path);
|
||||
}
|
||||
} catch (_) {
|
||||
content = null;
|
||||
@ -78,7 +72,10 @@ class AssetsFileDataSourceImpl extends I18nDataSource {
|
||||
/// default i18n file.
|
||||
if (content == null && locale != null) {
|
||||
try {
|
||||
content = await rootBundle.loadString('$basePath/$baseName.$ext');
|
||||
final fallbackPath = AssetsUtils.cleanPath(
|
||||
'$basePath/$baseName.$defaultLocale.$ext',
|
||||
);
|
||||
content = await assetBundle.loadString(fallbackPath);
|
||||
} catch (_) {
|
||||
throw SourceNotFoundException(path, format: format);
|
||||
}
|
||||
@ -98,7 +95,7 @@ class AssetsFileDataSourceImpl extends I18nDataSource {
|
||||
Future<String> _tryLoadUri(Uri uri) async {
|
||||
String? content;
|
||||
try {
|
||||
content = await rootBundle.loadString(uri.toString());
|
||||
content = await assetBundle.loadString(uri.toString());
|
||||
} catch (_) {
|
||||
throw SourceNotFoundException(uri.toString(), format: format);
|
||||
}
|
||||
|
@ -17,23 +17,33 @@
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
import 'package:wyatt_i18n/src/core/enums/format.dart';
|
||||
|
||||
/// {@template i18n_data_source}
|
||||
/// Base class for i18n data sources.
|
||||
///
|
||||
///
|
||||
/// This class is used to load i18n files from a source.
|
||||
/// It returns a [Future] that resolves to a [String] containing the i18n file
|
||||
/// contents.
|
||||
/// {@endtemplate}
|
||||
abstract class I18nDataSource extends BaseDataSource {
|
||||
const I18nDataSource({this.format = Format.arb});
|
||||
/// {@macro i18n_data_source}
|
||||
const I18nDataSource({
|
||||
this.format = Format.arb,
|
||||
this.defaultLocale = 'en',
|
||||
});
|
||||
|
||||
/// The format of the i18n file.
|
||||
final Format format;
|
||||
|
||||
/// The default locale.
|
||||
final String defaultLocale;
|
||||
|
||||
/// Loads the i18n file from the source.
|
||||
/// If [locale] is not `null`, it will load the file with the given [locale].
|
||||
/// Otherwise, it will load the file from the default location.
|
||||
Future<String> load({required String? locale});
|
||||
|
||||
/// Loads the i18n file from the source.
|
||||
///
|
||||
///
|
||||
/// This method is used to load the i18n file from the given [Uri].
|
||||
Future<String> loadFrom(Uri uri);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user