Thursday 28 February 2013

Enum translation converter

         To follow up the previous entry on enums nad translations, I'll continue by adding some more functionality which helps in a similar manner. In some instances we needed to display an enum declared in the ViewModel  in a textbox or a column - specifically we  needed the enum's translation,  and that's where this converter came into play.

Code Snippet
  1. public class TranslateEnumConverter : MarkupExtension, IValueConverter
  2. {
  3.     public static TranslateEnumConverter _converter = null;                  

  4.     public TranslateEnumConverter()
  5.     {        
  6.     }
  7.  
  8.     public object ConvertBack(object value, Type targetType, object     parameter, System.Globalization.CultureInfo culture)
  9.     {
  10.         throw new NotImplementedException();
  11.     }
  12.  
  13.     public override object ProvideValue(IServiceProvider serviceProvider)
  14.     {
  15.         if (_converter == null)
  16.         {
  17.             _converter = new TranslateEnumConverter();
  18.         }
  19.         return _converter;
  20.     }
  21. }

          Let's start with nearly ordinary Converter class above. What's a bit different is using MarkupExtension as one of the ways to allow adding converter to binding in XAML without the need of declaring it as a resource. The pretty straightforward use of ProvideValue allows us exactly this:

Converter={Converters:TranslateEnumConverter}


Converters is the namespace where all our converters reside.
The Convert method, as in any converter, returns the converted value from VM to View. In our case it gets the resource and the translated string of the enum and returns it.

Code Snippet
  1. public object Convert(object value, Type targetType,
  2.     object parameter, System.Globalization.CultureInfo culture)
  3. {
  4.     if (value == null)
  5.         return String.Empty;
  6.  
  7.     if (parameter == null)
  8.         throw new ArgumentNullException("parameter");
  9.  
  10.     String inputParam = parameter.ToString();
  11.     String resourceName = String.Empty;
  12.   
  13.     resourceName = parameter.ToString();
  14.  
  15.     Type type = Type.GetType(resourceName);
  16.     string name = value.ToString();
  17.     if (type == null)      // Invalid resource name
  18.         throw new ArgumentException("Resource name 
  19.                   should be a fully qualified name");
  20.  
  21.     var property = type.GetProperty(name, BindingFlags.Static |
  22.         BindingFlags.Public | BindingFlags.NonPublic);
  23.     string translation = string.Empty;
  24.        
  25.     if (property == null) // With no corresponding Resx translation, there's an error message displayed
  26.         translation = String.Format("Field {0} not found in the resource file {1}", name, resourceName);
  27.     else  
  28.         translation = property.GetValue(null, null).ToString();
  29.  
  30.     return translation;
  31. }

            You can read the previous post's description to gain more knowledge about how the resource name is passed into the converter and parsed into parameters - beside that the code above should be pretty self-explanatory. With the code we've got we can call the converter from XAML, with Status being the Enum property from the ViewModel and fully qualified name of the resource class as the ConverterParameter:

Binding="{Binding Status,
Converter={Converters:TranslateEnumConverter}, 
ConverterParameter='Mod.Ule.Resources.Enums.EnumStrings,Mod.Ule'}"

2 comments:

  1. Hi Simon,

    Do you need a collaborative tool to manage resx translation? If yes, I suggest the localization management platform https://poeditor.com

    This l10n solution supports other localization formats too, like iOS .strings, Java .properties, Android XML and so forth

    I think it's a nice and flexible way to translate apps or websites.

    Cheers!

    ReplyDelete