简体   繁体   中英

Add localization resources to be shared across multiple projects

Due to architecture design specifications, I have an application that fills its views from ClassLibraries . The application itself behaves like a sort of Integrator.

Now I need to add localization resources and I can successfully achieve it by adding *.resw files but only if the control is declared inside of the Application project .

What I actually need is to being able to share those resources across the ENTIRE SOLUTION somehow.

Then, the point is to being able to translate any control's content of the solution by using localization resources, preferably using the structure explained above.

For example, I have this following view, which fills the TextBlocks ' content depending on the selected language:

<ComboBox x:Name="Languages"
              ItemsSource="{Binding Languages}"
              SelectedItem="{Binding SelectedLanguage, Mode=TwoWay}">
        <i:Interaction.Behaviors>
            <iCore:EventTriggerBehavior EventName="SelectionChanged">
                <iCore:InvokeCommandAction Command="{Binding ChangeLanguage}" />
            </iCore:EventTriggerBehavior>
        </i:Interaction.Behaviors>

        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding LanguageName}" />
            </DataTemplate>
        </ComboBox.ItemTemplate>

    </ComboBox>

    <TextBlock Text="{Binding Model.HelloText}" FontSize="50" Foreground="Red"/>
    <TextBlock Text="{Binding Model.HowAreYouText}" FontSize="50" Foreground="Red"/>
    <BFview:BFView />
</StackPanel>

Where BFView is a view stored in another project (has two dummy textblocks also)

The Model of that view:

public class MainModel : TranslatableStrings
    {
        private string helloText, howareuText;

        public string HelloText
        {
            get { return this.helloText; }
            set { SetProperty(ref this.helloText, value); }
        }

        public string HowAreYouText
        {
            get { return this.howareuText; }
            set { SetProperty(ref this.howareuText, value); }
        }

    }

And the base class of the Model is just a contractual class since it has no implementation, but a base type:

public abstract class TranslatableStrings : BindableBase { }

Then, the View data context is the following one:

public class MainViewModel : BaseViewModel
    {
        private ObservableCollection<MainViewListRscs> languages = new ObservableCollection<MainViewListRscs>();
        private ICommand changeLang;
        private MainModel model = new MainModel();

        public MainViewModel()
        {
            Languages = new ObservableCollection<MainViewListRscs>()
            {
                new MainViewListRscs { LanguageCode = "es-ES", LanguageName = "Español" },
                new MainViewListRscs { LanguageCode = "en-EN", LanguageName = "English" },
                new MainViewListRscs { LanguageCode = "fr-FR", LanguageName = "Français" },
                new MainViewListRscs { LanguageCode = "de-DE", LanguageName = "Deutsch" }
            };

        }

        public ICommand ChangeLanguage
        {
            get { return changeLang = changeLang ?? new DelegateCommand(OnChangeLanguageRequested); }
        }

        public ObservableCollection<MainViewListRscs> Languages
        {
            get { return this.languages; }
            set
            {
                this.languages = value;
                OnPropertyChanged();
            }
        }

        public MainViewListRscs SelectedLanguage { get; set; }

        public MainModel Model
        {
            get { return this.model; }
            set { this.model = value; }
        }

        private void OnChangeLanguageRequested()
        {
            Logger.Debug("MAINVIEW", SelectedLanguage.LanguageName + " selected.");
            TranslateManager.UpdateStrings<TranslatableStrings>(SelectedLanguage.LanguageCode, this.Model);
        }

        public override Task OnNavigatedFrom(NavigationEventArgs args)
        {
            return null;
        }

        public override Task OnNavigatedTo(NavigationEventArgs args)
        {
            return null;
        }
    }

And the TranslateManager :

public class TranslateManager
    {
        public async static void UpdateStrings<T>(string langCode, T instance) where T : TranslatableStrings
        {
            //Get all the classes that implement TranslatableStrings
            var currentAssembly = instance.GetType().GetTypeInfo().Assembly;
            var translatableClasses = currentAssembly.DefinedTypes.Where(type => type.BaseType == typeof(T)).ToList();

            //Open RESX file
            ResourceLoader resx = ResourceLoader.GetForCurrentView(langCode);

            foreach(var Class in translatableClasses)
            {
                foreach(var property in Class.DeclaredProperties)
                {
                    string value = resx.GetString(property.Name);
                    var vmProp = instance.GetType().GetTypeInfo().GetDeclaredProperty(property.Name);
                    vmProp.SetValue(instance, value);
                }
            }

        }

    }

I have achieved changing the two TextBlocks of the MainView but not the view in another project. What I would need to do is to get a list of assemblies contained in a solution. I guess that getting just this would make everything work since I'm using a generic implementation.

Any suggestion will be much appreciated.

Thanks!

Your translation files are loaded as resources. So you can access them anywhere, even in other projects by doing something like

private ResourceLoader _resourceLoader = new ResourceLoader();
var someTranslation =_resourceLoader.GetString("your_localization_key");

Wrap this code nicely into a lib so that you can have an easy access to it from everywhere, and there you go !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM