Click here to Skip to main content
15,886,518 members
Articles / Desktop Programming / WPF

C.B.R.

Rate me:
Please Sign up or sign in to vote.
4.96/5 (52 votes)
22 Oct 2012GPL329 min read 124.3K   1.8K   132  
Comic and electronic publication reader with library management, extended file conversion, and devices support.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;

namespace CBR.Core.Helpers.Localization
{
    public class CultureEventArgs : EventArgs
    {
        public CultureItem Culture { get; set; }
    }

    /// <summary>
    /// Culture event delegate signature
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void CultureEventArrived(object sender, CultureEventArgs e);

    /// <summary>
    /// Class that manage culture providers (act as a factory) and the UI language. Provide helper functions
    /// to get lists and allow to implement a resource provider
    /// </summary>
    public class CultureManager
    {
        #region ----------------SINGLETON----------------
		/// <summary>
		/// Singleton
		/// </summary>
		public static readonly CultureManager Instance = new CultureManager();

		/// <summary>
		/// Private constructor for singleton pattern
		/// </summary>
        private CultureManager()
		{
		}
		#endregion

        #region ----------------PROPERTIES----------------

        private CultureInfo _uiCulture;

        /// <summary>
        /// Sets the UICulture for the WPF application and raises the <see cref="UICultureChanged"/>
        /// event causing any XAML elements using the <see cref="ResxExtension"/> to automatically
        /// update
        /// </summary>
        public CultureInfo UICulture
        {
            get
            {
                if (_uiCulture == null)
                {
                    _uiCulture = Thread.CurrentThread.CurrentUICulture;
                }
                return _uiCulture;
            }
            set
            {
                if (value != UICulture)
                {
                    _uiCulture = value;
                    Thread.CurrentThread.CurrentUICulture = value;
                    if (SynchronizeThreadCulture)
                    {
                        SetThreadCulture(value);
                    }
                    //UICultureExtension.UpdateAllTargets();
                    MarkupExtensionManager.Instance.UpdateAllTargets();

                    if (UICultureChanged != null)
                        UICultureChanged(null, new CultureEventArgs()
                        {
                            Culture = CultureManager.Instance.GetAvailableCultures()
                                .First(p => p.Culture.TwoLetterISOLanguageName == _uiCulture.TwoLetterISOLanguageName)
                        });
                }
            }
        }

        private bool _synchronizeThreadCulture = true;

        /// <summary>
        /// If set to true then the <see cref="Thread.CurrentCulture"/> property is changed
        /// to match the current <see cref="UICulture"/>
        /// </summary>
        public bool SynchronizeThreadCulture
        {
            get { return _synchronizeThreadCulture; }
            set
            {
                _synchronizeThreadCulture = value;
                if (value)
                {
                    SetThreadCulture(UICulture);
                }
            }
        }

        /// <summary>
        /// internal resource provider
        /// </summary>
        internal IResourceProvider _resProvider = null;

        /// <summary>
        /// Current resource provider
        /// </summary>
        internal IResourceProvider Provider
        {
            get { if (_resProvider == null) _resProvider = GetResourceProvider(); return _resProvider; }
            set { _resProvider = value; }
        }

        #endregion

        #region ----------------EVENTS----------------

        /// <summary>
        /// Raised when the <see cref="UICulture"/> is changed
        /// </summary>
        /// <remarks>
        /// Since this event is static if the client object does not detach from the event a reference
        /// will be maintained to the client object preventing it from being garbage collected - thus
        /// causing a potential memory leak. 
        /// </remarks>
        public event CultureEventArrived UICultureChanged;

        /// <summary>
        /// Raised if the available culture list change
        /// </summary>
        public event CultureEventArrived AvailableCulturesChanged;

        #endregion

        #region ----------------METHODS----------------

        public void Refresh()
        {
            //UICultureExtension.UpdateAllTargets();
            MarkupExtensionManager.Instance.UpdateAllTargets();
        }

        /// <summary>
        /// Return a list of CultureItem discovered by the provider
        /// </summary>
        /// <returns></returns>
        public List<CultureItem> GetAvailableCultures()
        {
            return Provider.GetAvailableCultures();
        }

        /// <summary>
        /// Return a list of module or resx discovered by the provider
        /// </summary>
        /// <param name="code2Letter"></param>
        /// <returns></returns>
        public List<string> GetAvailableModules(string code2Letter)
        {
            return Provider.GetAvailableModules(code2Letter);
        }

        /// <summary>
        /// Return the resource list of LocalizationItem for a given module
        /// </summary>
        /// <param name="code2Letter"></param>
        /// <param name="modul"></param>
        /// <returns></returns>
        public List<LocalizationItem> GetModuleResource(string code2Letter, string modul)
        {
            return Provider.GetModuleResource(code2Letter, modul);
        }

        /// <summary>
        /// Ask the provider to save the resource (if possible...)
        /// </summary>
        public void SaveResources()
        {
            if (_resProvider != null)
                _resProvider.SaveDefaultResources();
        }

        /// <summary>
        /// This remove a resource from memory, more for developper when update or change the module
        /// or the default value to re create the resource (files mode)
        /// </summary>
        /// <param name="resource"></param>
        public void DeleteResource(string code2Letter, string modul, object resource)
        {
            if (_resProvider != null)
                _resProvider.DeleteResource( code2Letter,  modul, resource);
        }

        /// <summary>
        /// Ask the provider (if possible...) to create a new culture resource, need to be saved later
        /// </summary>
        /// <param name="info"></param>
        /// <param name="iconFile"></param>
        public void CreateCulture(CultureInfo info, string iconFile)
        {
            if (_resProvider != null)
            {
                CultureItem item = _resProvider.CreateCulture(info, iconFile);
                if (AvailableCulturesChanged != null)
                {
                    AvailableCulturesChanged(null, new CultureEventArgs() { Culture = item });
                }
            }
        }

        #endregion

        #region ----------------INTERNALS----------------

        /// <summary>
        /// Retreive a provider based on the configuration
        /// </summary>
        /// <returns></returns>
        private IResourceProvider GetResourceProvider()
        {
            switch (CBR.Core.Properties.Settings.Default.LocalizeProvider)
            {
                case ProviderMode.RESX:
                    return new ResxProvider();

                case ProviderMode.XML:
                    return new XmlProvider();

                case ProviderMode.BIN:
                    return new BinProvider();

                default: return null;
            }
        }

        /// <summary>
        /// Set the thread culture to the given culture
        /// </summary>
        /// <param name="value">The culture to set</param>
        /// <remarks>If the culture is neutral then creates a specific culture</remarks>
        private void SetThreadCulture(CultureInfo value)
        {
            if (value.IsNeutralCulture)
            {
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(value.Name);
            }
            else
            {
                Thread.CurrentThread.CurrentCulture = value;
            }
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect
France France
WPF and MVVM fan, I practice C # in all its forms from the beginning of the NET Framework without mentioning C ++ / MFC and other software packages such as databases, ASP, WCF, Web & Windows services, Application, and now Core and UWP.
In my wasted hours, I am guilty of having fathered C.B.R. and its cousins C.B.R. for WinRT and UWP on the Windows store.
But apart from that, I am a great handyman ... the house, a rocket stove to heat the jacuzzi and the last one: a wood oven for pizza, bread, and everything that goes inside

https://guillaumewaser.wordpress.com/
https://fouretcompagnie.wordpress.com/

Comments and Discussions