i18n(alarm): localize all native notification, channel and chooser texts
Centralize every native-side user-facing string in a single
AlarmNotificationStrings store written by Flutter via a new
setNotificationStrings MethodChannel whenever the app locale changes,
and read at notification/channel build time (with English fallbacks)
even when the engine is dead. This replaces the hardcoded Spanish text
in the ringing notification ("Alarma PluriWave", "Posponer", "Detener"),
the pre-notice notification ("Posponer", "Omitir esta vez"), both
notification channels (names + descriptions) and the file-action
choosers ("Abrir carpeta", "Abrir grabación").
The per-alarm preNoticeTemplate/snoozeCountdown template+label args are
dropped from scheduleAlarm and the persisted spec and folded into the
shared store, so a locale change now also relocalizes already-scheduled
alarms. Channels are re-created on each use so their name/description
refresh after a language switch.
Adds alarmRingingNotificationTitle, alarmFire/PreNoticeChannelName,
alarmFire/PreNoticeChannelDescription and openFolder/openRecording
chooser keys across all 13 locales (reusing snoozeAction, stopAlarmAction,
skipNextAction, snoozeAgainAction). Rewrites the template test around
setNotificationStrings. Kotlin is static-reviewed only; no Android build
environment available here.
This commit is contained in:
@@ -172,29 +172,41 @@ class ServicioAlarmasAndroid implements PuertoAlarmasAndroid {
|
||||
@override
|
||||
void configurarLocalizaciones(AppLocalizations l10n) {
|
||||
_l10n = l10n;
|
||||
// Push every localized notification/channel/chooser string to the native
|
||||
// side so it can build localized notifications even when the Flutter engine
|
||||
// is dead (alarm fired from a killed app). Fire-and-forget; runs once per
|
||||
// locale change (callers guard against per-rebuild churn).
|
||||
unawaited(_enviarTextosNotificacion(l10n));
|
||||
}
|
||||
|
||||
/// Builds a pre-notice template string with a literal `{minutes}` placeholder
|
||||
/// for Kotlin to replace at broadcast-receiver fire time.
|
||||
///
|
||||
/// Strategy: call [preNoticeCountdown] with a unique sentinel integer and
|
||||
/// replace the sentinel's string representation with `{minutes}`.
|
||||
static String _preNoticeTemplate(AppLocalizations l10n) {
|
||||
const sentinel = 42424242;
|
||||
return l10n.preNoticeCountdown(sentinel).replaceFirst(
|
||||
sentinel.toString(),
|
||||
'{minutes}',
|
||||
);
|
||||
Future<void> _enviarTextosNotificacion(AppLocalizations l10n) async {
|
||||
try {
|
||||
await _channel.invokeMethod<void>('setNotificationStrings', {
|
||||
'ringTitle': l10n.alarmRingingNotificationTitle,
|
||||
'snoozeLabel': l10n.snoozeAction,
|
||||
'stopLabel': l10n.stopAlarmAction,
|
||||
'skipLabel': l10n.skipNextAction,
|
||||
'snoozeAgainLabel': l10n.snoozeAgainAction,
|
||||
'fireChannelName': l10n.alarmFireChannelName,
|
||||
'fireChannelDescription': l10n.alarmFireChannelDescription,
|
||||
'preNoticeChannelName': l10n.alarmPreNoticeChannelName,
|
||||
'preNoticeChannelDescription': l10n.alarmPreNoticeChannelDescription,
|
||||
'preNoticeTemplate': _plantillaMinutos(l10n.preNoticeCountdown),
|
||||
'snoozeCountdownTemplate': _plantillaMinutos(l10n.snoozeCountdown),
|
||||
'openFolderTitle': l10n.openFolderChooserTitle,
|
||||
'openRecordingTitle': l10n.openRecordingChooserTitle,
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint('[PluriWave][alarmas] setNotificationStrings ERROR $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Same sentinel strategy as [_preNoticeTemplate], but for the snooze
|
||||
/// countdown notification re-posted every minute while an alarm is snoozed.
|
||||
static String _snoozeCountdownTemplate(AppLocalizations l10n) {
|
||||
/// Turns a localized `{int} -> String` message into a template with a literal
|
||||
/// `{minutes}` placeholder for Kotlin to fill at fire time: it calls the
|
||||
/// message with a unique sentinel and swaps the sentinel back for `{minutes}`.
|
||||
static String _plantillaMinutos(String Function(int) traducir) {
|
||||
const sentinel = 42424242;
|
||||
return l10n.snoozeCountdown(sentinel).replaceFirst(
|
||||
sentinel.toString(),
|
||||
'{minutes}',
|
||||
);
|
||||
return traducir(sentinel).replaceFirst(sentinel.toString(), '{minutes}');
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -216,10 +228,6 @@ class ServicioAlarmasAndroid implements PuertoAlarmasAndroid {
|
||||
final programada = await _channel.invokeMethod<bool>('scheduleAlarm', {
|
||||
'id': alarma.id,
|
||||
'title': localizedAlarmName(_textos, alarma.nombre),
|
||||
'preNoticeTemplate': _preNoticeTemplate(_textos),
|
||||
'snoozeCountdownTemplate': _snoozeCountdownTemplate(_textos),
|
||||
'snoozeAgainLabel': _textos.snoozeAgainAction,
|
||||
'snoozeStopLabel': _textos.stopAlarmAction,
|
||||
'triggerAtMillis': proxima.millisecondsSinceEpoch,
|
||||
'preNoticeAtMillis':
|
||||
alarma.snoozeHasta == null
|
||||
|
||||
Reference in New Issue
Block a user