samc
Topic Author
Posts: 74
Joined: 21 Aug 2019, 19:22

localization change from data trigger

29 Mar 2024, 00:32

Hi there,

We're doing something maybe not very standard. We had a generic "OK" dialog that we use to display error messages. This dialog can display any number of error messages, and in some cases it changes options (instead of just "OK" it might have "retry" or "cancel" options as well). Originally, the data model for this was just that we'd set an enum with the type of data dialog we had to display. The dialog had data triggers on the enum, and those data triggers would configure the dialog to appear with a proper message and buttons.

We attempted to switch this dialog to use data triggers to change the message using localization, but it doesn't seem to work -- we just see the localization lookup 'key'. As a temp workaround, we have instead just changed the data model so we can also just bind the message, which we are now just manually looking up. Is that the best way to do this? Or should we be able to bind a localized string through a data trigger somehow? Or is another approach better?

thanks,
sam
 
samc
Topic Author
Posts: 74
Joined: 21 Aug 2019, 19:22

Re: localization change from data trigger

29 Mar 2024, 00:38

Wanted to note we also tried this with a storyboard kind of like this, which also didn't seem to work:
<StringAnimationUsingKeyFrames Storyboard.TargetName="Status" Storyboard.TargetProperty="(TextBlock.Text)">
    <DiscreteStringKeyFrame KeyTime="00:00:00" Value="{noesis:Loc Text.Key.Here}"/>
</StringAnimationUsingKeyFrames>
thanks,
sam
 
User avatar
sfernandez
Site Admin
Posts: 2997
Joined: 22 Dec 2011, 19:20

Re: localization change from data trigger

02 Apr 2024, 11:58

Hello,

Let me see if I understood correctly the problem you have. You want to show a different dialog message depending on some enums in the viewmodel, and then have the message localized, right? Couldn't you just have the different texts in the DataTemplate and show the appropriate one?
<DataTemplate>
  <Grid>
    <TextBlock x:Name="txt1" Text="{noesis:Loc Option1Text}" Visibility="Visible"/>
    <TextBlock x:Name="txt2" Text="{noesis:Loc Option2Text}" Visibility="Collapsed"/>
  </Grid>
  <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Option}" Value="Option2">
      <Setter TargetName="txt1" Property="Visibility" Value="Collapsed"/>
      <Setter TargetName="txt2" Property="Visibility" Value="Visible"/>
    </DataTrigger>
  </DataTemplate.Triggers>
</DataTemplate>
 
samc
Topic Author
Posts: 74
Joined: 21 Aug 2019, 19:22

Re: localization change from data trigger

03 Apr 2024, 19:14

We can certainly try that. I think we were avoiding that option because it gets unwieldy if you have more than just a couple options, and it's also harder to maintain with each new option you add.

thanks,
sam
 
User avatar
nadjibus
Posts: 32
Joined: 24 Feb 2022, 04:09

Re: localization change from data trigger

04 Apr 2024, 20:50

What we ended doing is create a MarkupExtension TranslateExtension that provides a binding to a "LocalizedString" class that's responsible for listening to Culture change and updates its content:
[ContentProperty(nameof(Key))]
    public class TranslateExtension : MarkupExtension
    {
        public string Key { get; set; }
        
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            try
            {
                // Your language service that triggers an event when the Culture is changed. Here we're using a ServiceLocator to get it
                // but it can just be a singleton
                var languageService = ServiceLocator.Instance?.GetService<ILanguageService>();
                
                if (languageService == null)
                    return Key;

                // If serviceProvider is already a Binding, just return the translation directly
                if (serviceProvider is IProvideValueTarget provideValueTarget && provideValueTarget.TargetObject is BindingBase)
                {
                    var result = TextResources.ResourceManager.GetString(Key);
                    return result;
                }

                // Create a Binding to a a new LocalizedString.Value and return it
                var binding = new Binding(nameof(LocalizedString.Value))
                {
                    Source = new LocalizedString(Key, languageService)
                };

                return binding.ProvideValue(serviceProvider);
            }
            catch
            {
                return Key;
            }
        }
    }
    
    public class LocalizedString : INotifyPropertyChanged                        
    {
        private static readonly WeakEventManager WeakEventManager = new();

        public LocalizedString(string key, ILanguageService languageService)
        {
            Key = key;

            // We're using a WeakEventManager to listen to the Culture change event, you can use any event bus/messaging system
            WeakEventManager.AddWeakEventListener<ILanguageService, LanguageChangedEventArgs>(languageService, nameof(languageService.LanguageChanged), OnLanguageChanged);

            SetValue();
        }

        private void SetValue()
        {
            // Get the localized string value, here we're using our ResourceManager that knows the current culture (via CultureInfo.CurrentCulture)
            Value = TextResources.ResourceManager.GetString(Key);
        }

        public string Key { get; }

        public string Value { get; private set; }

        private void OnLanguageChanged(object sender, LanguageChangedEventArgs e)
        {
            // If the culture changes, we reset the value and trigger PropertyChanged event so the UI will update itself
            SetValue();
            OnPropertyChanged(nameof(Value));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
Usage:
<TextBlock Text="{t:Translate Hello World!}" />
 
User avatar
sfernandez
Site Admin
Posts: 2997
Joined: 22 Dec 2011, 19:20

Re: localization change from data trigger

10 Apr 2024, 10:56

Hi Sam, if you need support for using LocExtension as a Setter value, could you please open a ticket about it. We will try to find a way to make it work in those scenarios too.

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 2 guests