Change language runtime with wrapped language resources Xamarin Forms

和自甴很熟 提交于 2021-02-10 05:42:09

问题


We are developing several mobile apps, with Common .NET Standard library between them, which holds the common functionallity. (MVVM) The Common project has a TranslationManager Class, and a Resource file, which holds the common translations. TranslationManager uses constructor injection, to inject the app specific translation resources.

    public TranslationManager(ResourceManager appSpecificLanguageResources)
    {
        _commonResources = CommonTranslationResources.ResourceManager;
        _appSpecificLanguageResources = appSpecificLanguageResources;
    }

With this code, we earn the possibilty to use common translations, and application specific translations with using only one Translation provider.

            if (string.IsNullOrWhiteSpace(translationKey))
                return null;
            string commonTranslation = _commonResources.GetString(translationKey, new CultureInfo(_preferenceCache.CultureName));
            string appSpecificTranslation = _appSpecificLanguageResources.GetString(translationKey, new CultureInfo(_preferenceCache.CultureName));
            if (commonTranslation == null && appSpecificTranslation == null)
            {
                MobileLogger.Instance.LogWarning($"Translate could not found by translationKey: {translationKey}");
                return $"TRANSLATION_{translationKey}";
            }
            if (!string.IsNullOrWhiteSpace(commonTranslation) && !string.IsNullOrWhiteSpace(appSpecificTranslation))
            {
                MobileLogger.Instance.LogDebug(TAG, $"Warning! Duplicate translate found for '{translationKey}' translationkey. Common translate is : '{commonTranslation}' , AppSpecific Translation is: {appSpecificTranslation}. Returning with appspecific translation.");
                return appSpecificTranslation;
            }
            if (commonTranslation == null)
                return appSpecificTranslation;
            else
                return commonTranslation;

In XAML, we have one MarkupExtension which provides the translation for the current language.

public class TranslateMarkupExtension : IMarkupExtension
{
    public TranslateMarkupExtension()
    {

    }

    public string TranslationKey { get; set; }

    public object ProvideValue(IServiceProvider serviceProvider)
    {
        if (string.IsNullOrWhiteSpace(TranslationKey)) return "nullref";
        return Resolver.Resolve<TranslationManager>().GetTranslationByKeyForCurrentCulture(TranslationKey);
    }
}

XAML Usage seem to be like:

  Entry Placeholder="{extensions:TranslateMarkup TranslationKey=PlaceholderPhoneNumber}"

The problem is, when i set the language at runtime, the translation extension markup does not evaluate the new translation.

Raising propertychanged with null parameter refreshes the bindings on the view, but does not affect MarkupExtensions.

I do not want to push the same page to the navigation stack, it seems patchwork for me.


回答1:


The problem is, when i set the language at runtime, the translation extension markup does not evaluate the new translation.

you may need to use INotifyPropertychanged interface for TranslationManager,when you change UI culture, all string that are bound to the index would update.

More detailed info, please refer to:

Xamarin.Forms change UI language at runtime (XAML)




回答2:


public class TranslateExtension : IMarkupExtension<BindingBase>
{       
    public TranslateExtension(string text)
    {
        Text = text;            
    }

    public string Text { get; set; }

    object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
    {
        return ProvideValue(serviceProvider);
    }

    public BindingBase ProvideValue(IServiceProvider serviceProvider)
    {
        var binding = new Binding
        {
            Mode = BindingMode.OneWay,
            Path = $"[{Text}]",
                Source = Translator.Instance,
        };
    return binding;
    }        
}

and this the Translator class as initially proposed, but reproduced here for clarity with the GetString call:

public class Translator : INotifyPropertyChanged
{
    public string this[string text]
    {
    get
    {
        return Strings.ResourceManager.GetString(text, Strings.Culture);
    }
    }        

    public static Translator Instance { get; } = new Translator();

    public event PropertyChangedEventHandler PropertyChanged;

    public void Invalidate()
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
    }
}

Binding text with:

{i18n:Translate Label_Text}

To trigger the update of languages you just then need to call:

Translator.Instance.Invalidate()

Solution from: https://forums.xamarin.com/discussion/82458/binding-indexername-and-binding-providevalue-in-xamarin-forms



来源:https://stackoverflow.com/questions/57636734/change-language-runtime-with-wrapped-language-resources-xamarin-forms

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!