Flutter - TimeOfDay - how to set locale - flutter

I have a Flutter multi-lingual app. It has a language selector, which allows to select a language among predefined list.
I successfully handle loading of my text labels.
I have however two major classes, where I have to manually set locale, when the user changes it:
DateTime and more specifically its formatting methods e.g. DateFormat.MMMEd([locale]). This one however is easy, since it supports locale as parameter. I have no issue with it;
TimeOfDay - it has format(context) method, however this method formats TimeOfDay instance according to MaterialLocalizations.formatTimeOfDay method internally to format the time and I cannot see how I can pass currently selected app locale.
So my question basically is how to set locale, when TimeOfDay.format method is executed?
The other related to above is showTimePicker, but I guess both inquires will have the same solution.

I was having the same issue with locales, And I figured out it's better not to depend on flutter's locale. I'm using shared_preferences library to save the current locale that the user choose, and I can access it in my entire app. so basically you better save the locale in shared preference when the user decides the language. hope it helps

Actually, there are two missing pieces, which fix the issue:
Set locale value in when call MaterialApp, e.g.
:
MaterialApp(
title: Env.value.appName,
locale: allTranslations.locale,
...
);
When the user changes locale, I have to call setState and rebuild the app, hence new locale to be propagated properly.
That's all.

Related

Flutter: Localization from API call

I wish to localize a Flutter application where locales are fetched by an API call, given the requested language.
I was hoping to be able to use the Intl package or something similar, but I am not sure this is possible without the .arb files.
Any ideas on how to accomplish this without reinventing the wheel?
(Having the localizations stored locally is not an option)
Down below, you can see a class which is converted to a singleton pattern. You can use any service locator package. It will be the same thing.
Now you can call this class in your main function, default set to EN.
Now let's say, you want to support SPANISH and not want to use .arb files
Now you can call google translate and replace values with the existing one. for every variable. I hope this helps.
Use https://pub.dev/packages/localizely_sdk package, it provides what you want to achieve
Turns out easy_localization has the functionality described. Simply creating a custom HttpAssetLoader and passing it to the easy_localization initialization method works out of the box, and provides device language detection, and application rebuild on locale change as intended.

Force localeResolutionCallback upon language change

I'm confronted with an interesting problem. I am using "localeResolutionCallback" to set the locale on load and to detect when the user changes the language on the device. However i also want to be able to bypass it so the user can choose a separate language from the one his device is set to.
This seems to be impossible because "localeResolutionCallback" if i read the docs properly only works on load and when a device language was changed.
Does anyone know how to force it to trigger this function? I do not want to use the "locale" key of material app (which works) because i would have 2 similar operations that are conflicting and i absolutely need "localeResolutionCallback" for detection so that one wins.
Any ideas? Thanks
PS: i am indeed using a listener to rebuild materialapp but like i said it doesn't trigger "localeResolutionCallback "
You should use "locale" as you mentionned and then just return null if it's during a device language change. Do the opposite if it's a manual language set.

What should I use for i18n in Flutter: S.of(context) or S.current?

I'm using the i18n plugin for Flutter (I believe it's this one) that comes with Android Studio.
And in every example I see it says to use S.of(context).my_string to get the Strings but it always returns null.
If I use S.current.my_string, it seems to work.
So is S.current the right way to do it and every doc/tutorial out there is wrong, are they the same or what?
What I'm basically asking here, is what is the difference between them.
Seems like S.of(context) is initially available way to access localised string.
But sometimes you need to use it without Build Context (in ViewModel, for example). So S.current was added for these cases.
More info here

NSUserDefaults flexibility for version updates

I am using the NSUserDefaults' api -registerDefaults api to register the factory defaults of my application. All is fine for the first version of the application. But when I provide an update for the iPhone application, I have 3 criteria to make sure:
The user preferences of older version app should be intact.
Addition to the factory defaults specific to the new version should be applied.
Providing flexibility in the design to the future version updates so that the user defaults modifies itself based on the new version.
The api -registerDefaults does not register factory defaults in new version updates because a plist file containing user preferences already exists in the /Library/Preferences of sandbox. And in case if we reset the preferences with new factory defaults, user preferences of previous version will be lost.
I think there should be a design pattern to handle such cases, so in general how do we cater with such situations? Doesnt Apple provide any inherent support for this? Or am I missing some links, I tried googling around without any success.
Thanks,
Raj
If this list of items you're talking about is an array registered under a single key, then yes, a larger array passed to -registerDefaults: will be ignored in favor of the smaller array stored in the persistent plist. NSUserDefaults tracks stuff on a per-key basis, and doesn't do any interpretation of the contents you store in there, so it's not going to try to automagically merge previous array values with new array values, or anything daft like that.
If you want new items to be added to this array by default when the user upgrades, I would recommend adding the items explicitly to the key yourself by fetching the existing array, adding the new items, and then saving the larger array back to the user defaults again. You can use a separate boolean flag to indicate that the upgrade has been done, to ensure that the addition doesn't get performed multiple times.
What is the problem? If the user never changes (or more exactly: sets) a preference, the factory default will be used. If an update of your app changes the factory defaults, those will be used instead. If the user has set his own preference, that will continue to be used.
A new factory default doesn't (and shouldn't) overwrite an user set preference. NSUserDefaults does exactly what you seem to be after.
I agree with Johan Kool. User defaults work as they should. If there's a preference that you want changed (for whatever reason) in an updated app version, just slightly rename the preference. For example, if someValue was a preference in version 1, then in version 2 name it someValue_v2 and your new factory default will take effect.

GWT visualization API Motion Chart language

I'm using the gwt visualization library to display motion charts in a gwt app. However, the language shown in the chart is random (different language every time it loads).
This:
http://code.google.com/apis/visualization/documentation/using_overview.html#localization
says I can set it, but only through the load method. But the GWT load method does not allow me to set anything other than the version and Packages.
As far as I can tell, there is no way of explicitly setting the language using the GWT API.
Any ideas?
You can set the locale of a GWT application in many ways: Locales in GWT. My guess would be that the Visualization API uses that value to set its own locale value.
You should be able to do a quick test of this by appending locale=fr (change to your desired locale) to the address:
http://www.example.com/MyGwtApp.html?locale=fr
This will force that locale to be used by GWT.
Update: the AjaxLoader does support setting the language via the AjaxLoader.AjaxLoaderOptions:
AjaxLoaderOptions options = AjaxLoaderOptions.newInstance();
options.setLanguage("fr");
AjaxLoader.loadApi("visualization", "1", null, options);
I'm not sure you can use null for the callback parameter, but you get the general idea.
I've discovered that this is a bug, which I've submitted here:
http://code.google.com/p/gwt-google-apis/issues/detail?id=358