Open Overman775 opened 4 years ago
@pumuckelo nope, have an idea, I’ll implement it later
Isn't that already done?
I see a tr
function in public.dart that can be called without context
argument.
That would be very helpful.
@ncuillery even tr function doesn't need context but using tr outside the widget tree doesn't work
@ncuillery even tr function doesn't need context but using tr outside the widget tree doesn't work
Can you provide an example of your code and the errors you're getting? because the static tr() function works fine outside widget trees.
but how does it get access to the language files
@aissat #321 may be delete Localization.of(context)
from public.dart ?
context removed from tr() and plural() in PR #343
Can someone give an implementation example? The only way I can think of at the moment is:
EasyLocalizationController
controller.loadTranslations()
Localization
localization.load(translations)
localization.tr
That would also mean exposing EasyLocalizationController
and Translations
and Localization
. I finally got it to work. Someone should document the following somewhere, because it definitely is not currently.
First off: findSystemLocale()
will not work when called from an isolate in the background. Don't ask me why, I just had to debug that to find out it is the case. This is important, because therefore EasyLocalizationController.deviceLocale
will not be set.
Thus, you have to use the following code from an isolate:
Step 1:
Call context.resetLocale();
somewhere in MyApp.build()
, because the currently documented saveLocale
will not save anything anywhere. Calling resetLocale
will actually save the deviceLocale
to SharedPreferences
, which we can retrieve even in an isolate.
Step 2: code executed in the isolate
import 'package:easy_localization/src/easy_localization_controller.dart';
import 'package:easy_localization/src/localization.dart';
/// A manually created instance of Localization to enable translating without context.
final Localization L = Localization.instance;
/// Method to load translations since context is not available in isolate.
Future<void> loadTranslations() async {
//this will only set EasyLocalizationController.savedLocale
await EasyLocalizationController.initEasyLocation();
final controller = EasyLocalizationController(
saveLocale: true, //mandatory to use EasyLocalizationController.savedLocale
fallbackLocale: AppConstants.SUPPORTED_LOCALES[0],
supportedLocales: AppConstants.SUPPORTED_LOCALES,
assetLoader: const RootBundleAssetLoader(),
useOnlyLangCode: false,
useFallbackTranslations: true,
path: AppConstants.LOCALIZATION_ASSET_PATH,
onLoadError: (FlutterError e) {
},
);
//Load translations from assets
await controller.loadTranslations();
//load translations into exploitable data, kept in memory
Localization.load(controller.locale, translations: controller.translations, fallbackTranslations: controller.fallbackTranslations);
}
Step 3: now you can actually translate
L.tr(you_string_key);
I finally got it to work. Someone should document the following somewhere, because it definitely is not currently. First off:
findSystemLocale()
will not work when called from an isolate in the background. Don't ask me why, I just had to debug that to find out it is the case. This is important, because thereforeEasyLocalizationController.deviceLocale
will not be set. Thus, you have to use the following code from an isolate:Step 1:
Call
context.resetLocale();
somewhere inMyApp.build()
, because the currently documentedsaveLocale
will not save anything anywhere. CallingresetLocale
will actually save thedeviceLocale
toSharedPreferences
, which we can retrieve even in an isolate.Step 2: code executed in the isolate
import 'package:easy_localization/src/easy_localization_controller.dart'; import 'package:easy_localization/src/localization.dart';
/// A manually created instance of Localization to enable translating without context. final Localization L = Localization.instance;
/// Method to load translations since context is not available in isolate. Future<void> loadTranslations() async { //this will only set EasyLocalizationController.savedLocale await EasyLocalizationController.initEasyLocation(); final controller = EasyLocalizationController( saveLocale: true, //mandatory to use EasyLocalizationController.savedLocale fallbackLocale: AppConstants.SUPPORTED_LOCALES[0], supportedLocales: AppConstants.SUPPORTED_LOCALES, assetLoader: const RootBundleAssetLoader(), useOnlyLangCode: false, useFallbackTranslations: true, path: AppConstants.LOCALIZATION_ASSET_PATH, onLoadError: (FlutterError e) { }, ); //Load translations from assets await controller.loadTranslations(); //load translations into exploitable data, kept in memory Localization.load(controller.locale, translations: controller.translations, fallbackTranslations: controller.fallbackTranslations); }
Step 3: now you can actually translate
L.tr(you_string_key);
This solution worked but resetLocale saves the deviceLocale and inf deviceLocale wasn't in supportedLocale it will lead to an excpetion (ex: "assets/localizations/fr.json not found").
So instead of using resetLocale
I used setLocale(context.locale)
, this will make sure to save the fallbackLocale instead of deviceLocale if the deviceLocale not supported
I finally got it to work. Someone should document the following somewhere, because it definitely is not currently. First off:
findSystemLocale()
will not work when called from an isolate in the background. Don't ask me why, I just had to debug that to find out it is the case. This is important, because thereforeEasyLocalizationController.deviceLocale
will not be set. Thus, you have to use the following code from an isolate:Step 1:
Call
context.resetLocale();
somewhere inMyApp.build()
, because the currently documentedsaveLocale
will not save anything anywhere. CallingresetLocale
will actually save thedeviceLocale
toSharedPreferences
, which we can retrieve even in an isolate.Step 2: code executed in the isolate
import 'package:easy_localization/src/easy_localization_controller.dart'; import 'package:easy_localization/src/localization.dart';
/// A manually created instance of Localization to enable translating without context. final Localization L = Localization.instance;
/// Method to load translations since context is not available in isolate. Future<void> loadTranslations() async { //this will only set EasyLocalizationController.savedLocale await EasyLocalizationController.initEasyLocation(); final controller = EasyLocalizationController( saveLocale: true, //mandatory to use EasyLocalizationController.savedLocale fallbackLocale: AppConstants.SUPPORTED_LOCALES[0], supportedLocales: AppConstants.SUPPORTED_LOCALES, assetLoader: const RootBundleAssetLoader(), useOnlyLangCode: false, useFallbackTranslations: true, path: AppConstants.LOCALIZATION_ASSET_PATH, onLoadError: (FlutterError e) { }, ); //Load translations from assets await controller.loadTranslations(); //load translations into exploitable data, kept in memory Localization.load(controller.locale, translations: controller.translations, fallbackTranslations: controller.fallbackTranslations); }
Step 3: now you can actually translate
L.tr(you_string_key);
I am trying to implement your code but getting error Null check operator used on a null value
pointing to context.resetLocale()
method that I'm calling inside build()
method
final Localization L = Localization.instance;
Future<void> loadTranslations() async {...}
Future main() async {
await loadTranslations();
// await EasyLocalization.ensureInitialized();
runApp(
App(store: store)
// EasyLocalization(
// path: 'assets/translations',
// assetLoader: CodegenLoader(),
// supportedLocales: [
// Locale('en', 'US'),
// Locale('hr', 'HR'),
// ],
// child: App(store: store),
// ),
//....
@override
Widget build(BuildContext context) {
context.resetLocale(); // error pointing here
I had the same issue as @nkulic and I had to change the assetLoader because I use CodeGen.
import 'package:weddy/gen/codegen_loader.g.dart';
...
assetLoader: const CodegenLoader(),
and I could remove context.resetLocale();
it wasn't necessary anymore.
I had the same issue as @nkulic and I had to change the assetLoader because I use CodeGen.
import 'package:weddy/gen/codegen_loader.g.dart'; ... assetLoader: const CodegenLoader(),
and I could remove
context.resetLocale();
it wasn't necessary anymore.
I ended up using a very recent and new package fast_i18n
I finally got it to work. Someone should document the following somewhere, because it definitely is not currently. First off:
findSystemLocale()
will not work when called from an isolate in the background. Don't ask me why, I just had to debug that to find out it is the case. This is important, because thereforeEasyLocalizationController.deviceLocale
will not be set. Thus, you have to use the following code from an isolate:Step 1:
Call
context.resetLocale();
somewhere inMyApp.build()
, because the currently documentedsaveLocale
will not save anything anywhere. CallingresetLocale
will actually save thedeviceLocale
toSharedPreferences
, which we can retrieve even in an isolate.Step 2: code executed in the isolate
import 'package:easy_localization/src/easy_localization_controller.dart'; import 'package:easy_localization/src/localization.dart';
/// A manually created instance of Localization to enable translating without context. final Localization L = Localization.instance;
/// Method to load translations since context is not available in isolate. Future<void> loadTranslations() async { //this will only set EasyLocalizationController.savedLocale await EasyLocalizationController.initEasyLocation(); final controller = EasyLocalizationController( saveLocale: true, //mandatory to use EasyLocalizationController.savedLocale fallbackLocale: AppConstants.SUPPORTED_LOCALES[0], supportedLocales: AppConstants.SUPPORTED_LOCALES, assetLoader: const RootBundleAssetLoader(), useOnlyLangCode: false, useFallbackTranslations: true, path: AppConstants.LOCALIZATION_ASSET_PATH, onLoadError: (FlutterError e) { }, ); //Load translations from assets await controller.loadTranslations(); //load translations into exploitable data, kept in memory Localization.load(controller.locale, translations: controller.translations, fallbackTranslations: controller.fallbackTranslations); }
Step 3: now you can actually translate
L.tr(you_string_key);
i have a similar problem and i tried this solution but im getting an error "MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)".
await EasyLocalizationController.initEasyLocation(); when this line is work i get this error. how can i solve this?
Thanks a lot for your help. It worked for me :heart:.
I wanted to get working translations in the background thread when using awesome_notifications—adding this to execute in the background thread when the main thread is dead worked for me.
await EasyLocalization.ensureInitialized();
final controller = EasyLocalizationController(
saveLocale: true,
fallbackLocale: const Locale('en'),
supportedLocales: const [
Locale('en'),
Locale('cs'),
],
assetLoader: const CodegenLoader(),
useOnlyLangCode: false,
useFallbackTranslations: true,
path: '/assets/translations/',
onLoadError: (FlutterError e) {},
);
//Load translations from assets
await controller.loadTranslations();
//load translations into exploitable data, kept in memory
Localization.load(controller.locale,
translations: controller.translations,
fallbackTranslations: controller.fallbackTranslations);
And then this worked normally: LocaleKeys.notifications_your_quote.tr()
In context:
static Future<void> onActionReceivedMethod(
ReceivedAction receivedAction) async {
SendPort? port = IsolateNameServer.lookupPortByName('main');
if (port != null) {
port.send(receivedAction);
} else {
if ((UniversalPlatform.isAndroid || UniversalPlatform.isIOS)) {
var quotesData = data;
if (await getLocaleIndex() == 1) {
quotesData = data_cz;
}
parseAllQuotes(quotesData).then((value) => quotesProvider = value);
}
await Hive.initFlutter();
Hive.registerAdapter(HabitAdapter());
Hive.registerAdapter(RewardAdapter());
Hive.registerAdapter(QuoteAdapter());
await Hive.openBox<Habit>(habitsBoxName);
await Hive.openBox(settingsBoxName);
await Hive.openBox<Reward>(rewardsBoxName);
await Hive.openBox<Quote>(favouriteQuotesBoxName);
await EasyLocalization.ensureInitialized();
final controller = EasyLocalizationController(
saveLocale: true,
fallbackLocale: const Locale('en'),
supportedLocales: const [
Locale('en'),
Locale('cs'),
],
assetLoader: const CodegenLoader(),
useOnlyLangCode: false,
useFallbackTranslations: true,
path: '/assets/translations/',
onLoadError: (FlutterError e) {},
);
//Load translations from assets
await controller.loadTranslations();
//load translations into exploitable data, kept in memory
Localization.load(controller.locale,
translations: controller.translations,
fallbackTranslations: controller.fallbackTranslations);
await AwesomeNotifications().initialize(
'resource://drawable/ic_stat_onesignal_default',
[
NotificationChannel(
channelKey: getChannelNameByType(NotificationSettings.habits),
channelName: getChannelNameByType(NotificationSettings.habits),
channelDescription:
LocaleKeys.notifications_habits_notifications.tr(),
defaultColor: primaryColor_74,
ledColor: Colors.blue,
enableLights: true,
importance: NotificationImportance.High,
channelShowBadge: true,
),
NotificationChannel(
channelKey: getChannelNameByType(NotificationSettings.quotes),
channelName: getChannelNameByType(NotificationSettings.quotes),
importance: NotificationImportance.Default,
channelDescription:
LocaleKeys.notifications_quotes_notifications.tr(),
defaultColor: secondaryColorGreen_43,
ledColor: Colors.green,
),
NotificationChannel(
channelKey: getChannelNameByType(NotificationSettings.rewards),
channelName: getChannelNameByType(NotificationSettings.rewards),
importance: NotificationImportance.Default,
channelDescription:
LocaleKeys.notifications_rewards_notifications.tr(),
defaultColor: Colors.black,
ledColor: Colors.green,
),
],
// debug: true,
);
await doneHabit(receivedAction);
}
}
Looks like we don't need code here, but just add one of the solutions to the documentation and maybe to the example
It's not necessary to always load the Localization
when running in isolate. The instance can now be passed as an input parameter. The only situation when it's required to load Localization
is when running from another Dart entry point.
Import Localization
class:
import 'package:easy_localization/src/localization.dart';
Pass the Localization.instance
as input parameter:
await compute(methodToRun, Localization.instance);
Get the translation:
localization.tr(<key>)
@bw-flagship it would be great if Localization
could be accessible without the need to import it specifically.
I see, thanks for the explanation! Feel free to open a pr :)
Hi, I'm trying to use EasyLocalization with WorkManager. When I try method with using EasyLocalizationController looks like there is no such class. Is this solution up to date?
@Mistic92 This solution is up-to-date, but I have no experience with work manager and can't tell you if this should work out of the box
@bw-flagship it worked, I had to explicitly import from
import 'package:easy_localization/src/localization.dart';
import 'package:easy_localization/src/easy_localization_controller.dart';
as Android Studio didn't want to import from that location. Even now I'm getting warning but solution works
Import of a library in the 'lib/src' directory of another package. (Documentation) Try importing a public library that exports this library, or removing the import.
@Mistic92 got it. Then #669 will work for you. However, it seems like it's not worked on at the moment
@Overman775 Hi Overmann, did you find a workaround to use localization outside of widgets?