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 | // You should have received a copy of the GNU General Public License | ||||||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| import 'dart:convert'; | import 'package:flutter/services.dart' show AssetBundle, rootBundle; | ||||||
| 
 |  | ||||||
| import 'package:flutter/services.dart' show ServicesBinding, rootBundle; |  | ||||||
| import 'package:wyatt_i18n/src/core/enums/format.dart'; | import 'package:wyatt_i18n/src/core/enums/format.dart'; | ||||||
| import 'package:wyatt_i18n/src/core/exceptions/exceptions.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'; | import 'package:wyatt_i18n/src/domain/data_sources/i18n_data_source.dart'; | ||||||
| 
 | 
 | ||||||
| /// {@template assets_file_data_source_impl} | /// {@template assets_file_data_source_impl} | ||||||
| @ -34,10 +33,11 @@ import 'package:wyatt_i18n/src/domain/data_sources/i18n_data_source.dart'; | |||||||
| /// {@endtemplate} | /// {@endtemplate} | ||||||
| class AssetsFileDataSourceImpl extends I18nDataSource { | class AssetsFileDataSourceImpl extends I18nDataSource { | ||||||
|   /// {@macro assets_file_data_source_impl} |   /// {@macro assets_file_data_source_impl} | ||||||
|   const AssetsFileDataSourceImpl({ |   AssetsFileDataSourceImpl({ | ||||||
|     this.basePath = 'assets', |     this.basePath = 'assets', | ||||||
|     this.baseName = 'i18n', |     this.baseName = 'i18n', | ||||||
|     super.format = Format.arb, |     super.format = Format.arb, | ||||||
|  |     super.defaultLocale = 'en', | ||||||
|   }) : super(); |   }) : super(); | ||||||
| 
 | 
 | ||||||
|   /// The folder where the i18n files are located. |   /// 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. |   /// The name of the i18n files without the extension. | ||||||
|   final String baseName; |   final String baseName; | ||||||
| 
 | 
 | ||||||
|   /// Checks if the given [assetPath] is a local asset. |   /// The asset bundle used to load the i18n files. | ||||||
|   /// |   final AssetBundle assetBundle = rootBundle; | ||||||
|   /// 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; |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   /// Tries to load the i18n file from the given [locale]. |   /// Tries to load the i18n file from the given [locale]. | ||||||
|   Future<String> _tryLoad(String? locale) async { |   Future<String> _tryLoad(String? locale) async { | ||||||
|     String? content; |     String? content; | ||||||
|     final ext = format.name; |     final ext = format.name; | ||||||
|     final path = locale == null | 
 | ||||||
|         ? '$basePath/$baseName.$ext' |     final path = AssetsUtils.cleanPath( | ||||||
|         : '$basePath/$baseName.$locale.$ext'; |       locale == null | ||||||
|  |           ? '$basePath/$baseName.$defaultLocale.$ext' | ||||||
|  |           : '$basePath/$baseName.$locale.$ext', | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|     try { |     try { | ||||||
|       if (await assetExists(path)) { |       if (await AssetsUtils.assetExists(path)) { | ||||||
|         content = await rootBundle.loadString(path); |         content = await assetBundle.loadString(path); | ||||||
|       } |       } | ||||||
|     } catch (_) { |     } catch (_) { | ||||||
|       content = null; |       content = null; | ||||||
| @ -78,7 +72,10 @@ class AssetsFileDataSourceImpl extends I18nDataSource { | |||||||
|     /// default i18n file. |     /// default i18n file. | ||||||
|     if (content == null && locale != null) { |     if (content == null && locale != null) { | ||||||
|       try { |       try { | ||||||
|         content = await rootBundle.loadString('$basePath/$baseName.$ext'); |         final fallbackPath = AssetsUtils.cleanPath( | ||||||
|  |           '$basePath/$baseName.$defaultLocale.$ext', | ||||||
|  |         ); | ||||||
|  |         content = await assetBundle.loadString(fallbackPath); | ||||||
|       } catch (_) { |       } catch (_) { | ||||||
|         throw SourceNotFoundException(path, format: format); |         throw SourceNotFoundException(path, format: format); | ||||||
|       } |       } | ||||||
| @ -98,7 +95,7 @@ class AssetsFileDataSourceImpl extends I18nDataSource { | |||||||
|   Future<String> _tryLoadUri(Uri uri) async { |   Future<String> _tryLoadUri(Uri uri) async { | ||||||
|     String? content; |     String? content; | ||||||
|     try { |     try { | ||||||
|       content = await rootBundle.loadString(uri.toString()); |       content = await assetBundle.loadString(uri.toString()); | ||||||
|     } catch (_) { |     } catch (_) { | ||||||
|       throw SourceNotFoundException(uri.toString(), format: format); |       throw SourceNotFoundException(uri.toString(), format: format); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -17,23 +17,33 @@ | |||||||
| import 'package:wyatt_architecture/wyatt_architecture.dart'; | import 'package:wyatt_architecture/wyatt_architecture.dart'; | ||||||
| import 'package:wyatt_i18n/src/core/enums/format.dart'; | import 'package:wyatt_i18n/src/core/enums/format.dart'; | ||||||
| 
 | 
 | ||||||
|  | /// {@template i18n_data_source} | ||||||
| /// Base class for i18n data sources. | /// Base class for i18n data sources. | ||||||
| ///  | /// | ||||||
| /// This class is used to load i18n files from a source. | /// This class is used to load i18n files from a source. | ||||||
| /// It returns a [Future] that resolves to a [String] containing the i18n file | /// It returns a [Future] that resolves to a [String] containing the i18n file | ||||||
| /// contents. | /// contents. | ||||||
|  | /// {@endtemplate} | ||||||
| abstract class I18nDataSource extends BaseDataSource { | 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; |   final Format format; | ||||||
| 
 | 
 | ||||||
|  |   /// The default locale. | ||||||
|  |   final String defaultLocale; | ||||||
|  | 
 | ||||||
|   /// Loads the i18n file from the source. |   /// Loads the i18n file from the source. | ||||||
|   /// If [locale] is not `null`, it will load the file with the given [locale]. |   /// If [locale] is not `null`, it will load the file with the given [locale]. | ||||||
|   /// Otherwise, it will load the file from the default location. |   /// Otherwise, it will load the file from the default location. | ||||||
|   Future<String> load({required String? locale}); |   Future<String> load({required String? locale}); | ||||||
| 
 | 
 | ||||||
|   /// Loads the i18n file from the source. |   /// Loads the i18n file from the source. | ||||||
|   ///  |   /// | ||||||
|   /// This method is used to load the i18n file from the given [Uri]. |   /// This method is used to load the i18n file from the given [Uri]. | ||||||
|   Future<String> loadFrom(Uri uri); |   Future<String> loadFrom(Uri uri); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user