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,16 +17,26 @@ | ||||
| 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. | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user