flutterfire
flutterfire copied to clipboard
[firebase_messaging] Localization of notifications does not work
The FCM fields used for localizing (I18N) the notification title and body are not working. For example:
{
"android" : {
"priority" : "normal",
"notification" : {
"title_loc_key": "notify_title",
"body_loc_key": "notify_body"
}
}
}
The FCM documentation states that these fields are used to localize the text in the "app's string resources", but Flutter does not have a res/values/strings.xml file.
I am using the flutter_localizations library, and maintain res/values/strings_<lang>.arb files as required by Flutter for internationalization, but there is no way for me to tell firebase_messaging to use these resources.
hI @bscottsmith This platform is not meant for assistance on personal code. Please see https://flutter.dev/community for resources and asking questions like this, you may also get some help if you post it on Stack Overflow. Closing, as this isn't an issue with Flutter itself, if you disagree please write in the comments and I will reopen it Thank you
I don't understand. How is the fact that firebase_messaging doesn't support localization of FCM notifications an issue with "personal code"? Are you saying that the title_loc_key and body_loc_key FCM fields are, in fact, supported by firebase_messaging, and therefore I may have a coding issue on my end?
@TahaTesser, I see that you assigned a type of "documentation" to this issue. Are you saying that the title_loc_key and body_loc_key FCM fields are, in fact, supported by firebase_messaging, and that it is simply not documented correctly? I would appreciate your input on this, as I can not find any way to support localization of the FCM notifications with the firebase_messaging plugin.
Hi @bscottsmith I assigned documentation label so we can have examples of localized notifications
@bscottsmith Hi, did you manage to have messages localized? I'm hitting the same wall here. https://github.com/FirebaseExtended/flutterfire/issues/2759
@vinnytwice: Nope. And unfortunately, it still isn't even assigned. @TahaTesser assigned this issue a type "documentation", which implies localization is supported and simply needs to be documented, so I worry this will never be assigned to a developer, even though I don't believe this plugin supports it at all (how do you document something that isn't supported?)...
@bscottsmith I see that @TahaTesser hasn't really answered that localization is supported, but it's fair to assume that. This is how I sent the notification, do you do anything different?
void sendBookingReceived(Booking booking) async {
print('sendBookingReceived() started');
var customerName = booking.customerName;
var bookingStart = booking.bookingStart;
var customerFCMToken = booking.customerFCMToken;
await post('https://fcm.googleapis.com/fcm/send',
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$firebaseServerKey'
},
body: jsonEncode({
'notification': <String, dynamic>{
'title_loc_key': 'BOOKING_RECEIVED_PUSH_SUBTITLE',
'title_loc_args': [booking.shopName],
'body_loc_key': 'BOOKING_RECEIVED_PUSH_BODY',
'body_loc_args': [
customerName,
'',
bookingStart
], //, bookingDate, bookingStart]),
'sound': 'true',
'mutable_content': 'true',
'content_available': 'true'
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done'
},
'to': customerFCMToken
})).whenComplete(() {
print('sendBookingReceived(): message sent');
}).catchError((e) {
print('sendBookingReceived() error: $e');
});
}
Also I had a look at the plugin code but I couldn't really see if it supports localization. So @TahaTesser I know that you guys are pretty busy but can you please make clear if it's supported or not? Really appreciate all the efforts.
Cheers
@bscottsmith It's fair to say there is no documentation for this, i couldn't find any but attempting to try it has some issues so i am assigning bug label too
@TahaTesser nice one, hope it gets fixed soon. Thanks for the clarification on the subject.
yes i hope to found this feature working soon
and it has to be localized according to Localizations.localeOf(context) => material app locale
I havent found any documentation for these fields but they are present in the firebase sdks. The following code is taken from the firebase admin nodejs sdk:
// admin.messaging.NotificationMessagePayload
/**
* Interface representing an FCM legacy API notification message payload.
* Notification messages let developers send up to 4KB of predefined
* key-value pairs. Accepted keys are outlined below.
*
* See [Build send requests](/docs/cloud-messaging/send-message)
* for code samples and detailed documentation.
*/
interface NotificationMessagePayload {
/**
* Identifier used to replace existing notifications in the notification drawer.
*
* If not specified, each request creates a new notification.
*
* If specified and a notification with the same tag is already being shown,
* the new notification replaces the existing one in the notification drawer.
*
* **Platforms:** Android
*/
tag?: string;
/**
* The notification's body text.
*
* **Platforms:** iOS, Android, Web
*/
body?: string;
/**
* The notification's icon.
*
* **Android:** Sets the notification icon to `myicon` for drawable resource
* `myicon`. If you don't send this key in the request, FCM displays the
* launcher icon specified in your app manifest.
*
* **Web:** The URL to use for the notification's icon.
*
* **Platforms:** Android, Web
*/
icon?: string;
/**
* The value of the badge on the home screen app icon.
*
* If not specified, the badge is not changed.
*
* If set to `0`, the badge is removed.
*
* **Platforms:** iOS
*/
badge?: string;
/**
* The notification icon's color, expressed in `#rrggbb` format.
*
* **Platforms:** Android
*/
color?: string;
/**
* The sound to be played when the device receives a notification. Supports
* "default" for the default notification sound of the device or the filename of a
* sound resource bundled in the app.
* Sound files must reside in `/res/raw/`.
*
* **Platforms:** Android
*/
sound?: string;
/**
* The notification's title.
*
* **Platforms:** iOS, Android, Web
*/
title?: string;
/**
* The key to the body string in the app's string resources to use to localize
* the body text to the user's current localization.
*
* **iOS:** Corresponds to `loc-key` in the APNs payload. See
* [Payload Key Reference](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html)
* and
* [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9)
* for more information.
*
* **Android:** See
* [String Resources](http://developer.android.com/guide/topics/resources/string-resource.html) * for more information.
*
* **Platforms:** iOS, Android
*/
bodyLocKey?: string;
/**
* Variable string values to be used in place of the format specifiers in
* `body_loc_key` to use to localize the body text to the user's current
* localization.
*
* The value should be a stringified JSON array.
*
* **iOS:** Corresponds to `loc-args` in the APNs payload. See
* [Payload Key Reference](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html)
* and
* [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9)
* for more information.
*
* **Android:** See
* [Formatting and Styling](http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling)
* for more information.
*
* **Platforms:** iOS, Android
*/
bodyLocArgs?: string;
/**
* Action associated with a user click on the notification. If specified, an
* activity with a matching Intent Filter is launched when a user clicks on the
* notification.
*
* * **Platforms:** Android
*/
clickAction?: string;
/**
* The key to the title string in the app's string resources to use to localize
* the title text to the user's current localization.
*
* **iOS:** Corresponds to `title-loc-key` in the APNs payload. See
* [Payload Key Reference](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html)
* and
* [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9)
* for more information.
*
* **Android:** See
* [String Resources](http://developer.android.com/guide/topics/resources/string-resource.html)
* for more information.
*
* **Platforms:** iOS, Android
*/
titleLocKey?: string;
/**
* Variable string values to be used in place of the format specifiers in
* `title_loc_key` to use to localize the title text to the user's current
* localization.
*
* The value should be a stringified JSON array.
*
* **iOS:** Corresponds to `title-loc-args` in the APNs payload. See
* [Payload Key Reference](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html)
* and
* [Localizing the Content of Your Remote Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH10-SW9)
* for more information.
*
* **Android:** See
* [Formatting and Styling](http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling)
* for more information.
*
* **Platforms:** iOS, Android
*/
titleLocArgs?: string;
[key: string]: string | undefined;
}
any update here
I'm waiting for it too
This would be awesome if we can find a solution for this!
Meanwhile, for a quick & dirty solution you could save the locale of the device (Platform.localeName) to the device token in your database and then send the correct message in your cloud function depending on the locale of the token.
As a workaround for android: we can create a file under the path: ../android/app/src/main/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="your_string_key">Your string</string>
</resources>
define all the default strings there and create separate files for localized countries (as usually native android works)
I suggest anyone who encounters this issue for now to use flutter_local_notifications together with intl_translation
I made a workaround for that if any one interested i created this package that allow me to display notification in foreground using locale notification and this one https://pub.dev/packages/fcm_config
so to translate notification i have to display it my self as next first from postman i send data only message
{
"priority": "high",
"to":"/topics/test_fcm_topic",
"data": {
"title_key": "New_Order_Title",
"body_key": "New_Order_Body",
"body_args": "150"
}
}
Next in my dart code
Map<String, Map<String, String>> translations = {
"ar": {
"New_Order_Title": "طلب جديد",
"New_Order_Body": "لديك طلب جديد برقم{args}",
},
"en": {
"New_Order_Title": "New order",
"New_Order_Body": "You has new order with number {args}",
}
};
Future<void> _firebaseMessagingBackgroundHandler(
RemoteMessage _notification) async {
var strings = translations[(await getSavedLocale()).languageCode];
if (strings == null) strings = translations["en"];
String title = strings[_notification.data["title_key"]];
String body = strings[_notification.data["body_key"]]
.replaceAll("{args}", _notification.data["body_args"]);
FCMConfig.displayNotification(title: title, body: body);
}
Future<Locale> getSavedLocale() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.reload();
var locale = prefs.containsKey("locale") ? prefs.getString("locale") : null;
return Locale(locale ?? Platform.localeName);
}
void main() async {
FCMConfig.init(onBackgroundMessage: _firebaseMessagingBackgroundHandler)
.then((value) {
FCMConfig.subscribeToTopic("test_fcm_topic");
});
runApp(MaterialApp(
home: MyHomePage(),
));
}
so what i do is saving my locale in shared preferences and retrieve it on background
on foreground i did this
//This how my plugin handle onMessage so don't be confused
@override
void onNotify(RemoteMessage notification) {
_firebaseMessagingBackgroundHandler(notification);
setState(() {
_notification = notification;
});
}
Hope this help any one
Any updates on this ?
as i see no progress on this i created a package to help localize notification if any one interested fcm_localization
Any updates on this ?
To use those loc_key fields in Android and IOS I've been using the native resource localization files:
On Android: strings.xml (/android/app/src/main/res/values/strings.xml)
on IOS: Localizable.strings (/ios/Runner/Base.lproj/Localizable.strings)
But I've got all these strings in a Flutter ARB as well. I just figured it's not possible to access the Flutter ARB for the loc_keys because of a native internal OS routine on Android and IOS that handles the localization of the strings based on only know about the native resource files. I think the handling of the loc_keys is out of the hands of the Flutter engine.
I use firebase_messaging for everything else.
@assemblethis I did the same thing , but when the app in foreground I get notification tile and body null , (just in android) do you have any adea ?
This is a useful feature to have as much can be localized for a flutter and firebase app with good documentation, hopefully some clear documentation or solution can come for localization in relation to FCM too!
Any updates on this? Are we supposed to create native string files just for cloud_messaging?
This problem stems from differences between old http api and new v1 api, in old api (like here, with fcm.googleapis.com/fcm/send) you need to use body_loc_key and title_loc_key inside notification object. But in v1 api you need to use bodyLocKey inside message.android.notification object. Like you see in documentation, it uses bodyLocKey inside notification object which will not work. You need to change field names to lowercase with underscores. I've just discovered this in my totally unrelated closed project, but want to share what is wrong.
Hi, any update here?
As per #9502 there is now documentation on how to do this :)
As per #9502 there is now documentation on how to do this :)
This isn't really a proper solution when the Flutter framework suggests to handle localization differently: https://docs.flutter.dev/development/accessibility-and-localization/internationalization
The proper solution likely involves either transpiling the .arb files to their respective platforms, or investigating/collaborating with the managers of the flutter_localizations package as it may already transpile to some degree and could be a more efficient route to complete this task.