Infralution Support Forum Index Infralution Support
Support groups for Infralution products
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Override resources at runtime

 
Post new topic   Reply to topic    Infralution Support Forum Index -> Globalizer Support
View previous topic :: View next topic  
Author Message
Andrew.W



Joined: 15 Apr 2015
Posts: 2
Location: Adelaide

PostPosted: Wed Apr 15, 2015 11:22 am    Post subject: Override resources at runtime Reply with quote

I have an existing application to be localized, and past versions allow users to customise various field labels. Many customers use these settings and we need to keep supporting it.

Is there a straightforward way of doing this in harmony with localized resx files?

I looked briefly at custom cultures but that seems like overkill, and I'm not sure how users could make changes at runtime.

I was hoping a custom culture file could be added to the top of the resx hierarchy,

i.e. custom > specific > neutral > invariant

If we allow overriding any text resource then customers in new countries could even translate the software and submit their 'custom culture' for including in the next upgrade. So is this possible somehow?
_________________
Andrew
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 4972

PostPosted: Wed Apr 15, 2015 11:33 pm    Post subject: Reply with quote

Is your application based on Windows Forms, WPF or ASP.NET?

Using the custom culture mechanism to support this would I think be somewhat messy. To use a custom culture you actually have to create/install the custom culture on the client PC - which seems fairly intrusive and heavy handed just to support customization of fields. In addition customers would have to use the Translator edition of Globalizer to compile the custom resources - this is quite a bit of work if they just want to change one or two resources.

If you are using WPF (with the ResxExension) then you would have the possibility of modifying the ResxExtension source code so that when looking for resources it first checks for a resx file containing custom resources and if the resource is present in this file uses it. You would probably just want to use one file for all custom resources and so would need to use a resource naming convention that include the window/form name.

For Windows Forms application it is a bit more difficult because you don't have a hook that you can use when the resource are being loaded. It might be possible for you to modify the CultureManager component that we provide for supporting dynamic culture changes to again read resources from a custom resource file and update the values in the form/user control. This would give you a general purpose mechanism for customizing any form text - however in this case you would need to modify each form to explicitly call this mechanism after the form is initialized.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Andrew.W



Joined: 15 Apr 2015
Posts: 2
Location: Adelaide

PostPosted: Wed Apr 22, 2015 10:09 am    Post subject: Reply with quote

Thanks for the quick response last week. My application is WPF and MVC.

I decided to create a T4 template to use on the resource files instead of ResXFileCodeGenerator.

Below is what works for me. In the generated class the string resource getters check a 'custom labels' dictionary before going to the resx file. I've hard-coded some constants to keep it simple. A more general implementation can be found here.

Code:
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Resources" #>
// ---------------------------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by the associated T4 template.
//     Any manual changes will be lost if the code is regenerated.
// </auto-generated>
// ---------------------------------------------------------------------------------------------------

<#
    const string fullNamespace = "Twoic.Pallets.Resources";
    const string path = @"D:\Source\Twoic.Pallets\Twoic.Pallets.Resources";
    const string baseName = "Content";
 #>
namespace <#=fullNamespace#>
{
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Drawing;
    using System.Globalization;
    using System.Resources;

    /// <summary>
    ///   A strongly-typed resource class, for looking up localized strings and other content.
    /// </summary>
   public class <#=baseName#>
    {
        private static ResourceManager manager;
        private static CultureInfo culture;
        private static Dictionary<string, string> customLabels = new Dictionary<string,string>();

        [SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal <#=baseName#>()
        {
        }

        /// <summary>
        ///   Returns the cached ResourceManager instance used by this class.
        /// </summary>
        public static ResourceManager ResourceManager
        {
            get
            {
                if (manager == null) manager = new ResourceManager("<#=fullNamespace#>.<#=baseName#>", typeof(<#=baseName#>).Assembly);
                return manager;
            }
        }

        /// <summary>
        ///   Overrides the current thread's CurrentUICulture property for all resource lookups.
        /// </summary>
        public static CultureInfo Culture
        {
            get { return culture; }
            set { culture = value; }
        }

        /// <summary>
        ///   Custom string resources that, if they exist, are used instead of resources in resx files.
        /// </summary>
        public static Dictionary<string, string> CustomLabels
        {
            get { return customLabels; }
            set { customLabels = value; }
        }
<#
    string fullPath = string.Format(@"{0}\{1}.resx", path, baseName);
    using (var reader = new ResXResourceReader(fullPath))
    {
        reader.UseResXDataNodes = true;
       
        foreach (DictionaryEntry entry in reader)
        {
            var key = (string)entry.Key;
            var node = (ResXDataNode)entry.Value;
            WriteLine("");
            if (!string.IsNullOrEmpty(node.Comment))
            {
                WriteLine("\t\t/// <summary>");
                WriteLine("\t\t///   {0}", node.Comment.Replace("\r\n", "\r\n\t\t///   "));
                WriteLine("\t\t/// </summary>");
            }
            if (node.FileRef == null)
            {
                WriteLine("\t\tpublic static string {0}", key);
                WriteLine("\t\t{");
                WriteLine("\t\t\tget");
                WriteLine("\t\t\t{");
                WriteLine("\t\t\t\tstring result = \"\";");
                WriteLine("\t\t\t\tif (!customLabels.TryGetValue(\"{0}\", out result))", key);
                WriteLine("\t\t\t\t\tresult = ResourceManager.GetString(\"{0}\", culture);", key);
                WriteLine("\t\t\t\treturn result;");
                WriteLine("\t\t\t}");
                WriteLine("\t\t}");
            }
            else
            {
                WriteLine("\t\tinternal static Bitmap {0}", key);
                WriteLine("\t\t{");
                WriteLine("\t\t\tget {{ return (Bitmap)ResourceManager.GetObject(\"{0}\", culture); }}", key);
                WriteLine("\t\t}");
            }
        }
    }
#>
    }
}

_________________
Andrew
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 4972

PostPosted: Wed Apr 22, 2015 11:20 pm    Post subject: Reply with quote

Thanks for sharing that. Are you using the Resource Wrapper localization method? I don't think the technique you are using would work for the Resx Extension localization method - because it does not access the resources through the designer generated code.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Infralution Support Forum Index -> Globalizer Support All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group