使用包装的语言资源Xamarin Forms更改语言运行时

时间:2019-08-24 09:35:04

标签: c# wpf xamarin xamarin.forms

我们正在开发几个移动应用程序,它们之间具有Common .NET Standard库,该库具有通用功能。 (MVVM) 通用项目有一个TranslationManager类和一个资源文件,其中包含通用翻译。 TranslationManager使用构造函数注入,以注入应用程序特定的翻译资源。

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

使用此代码,我们可以仅使用一个翻译提供程序即可使用常见翻译和特定于应用程序的翻译。

            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;

在XAML中,我们有一个MarkupExtension,它提供了当前语言的翻译。

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用法似乎像:

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

问题是,当我在运行时设置语言时,翻译扩展标记不会评估新翻译。

使用null参数更改的Raise属性会刷新视图上的绑定,但不会影响MarkupExtensions。

我不想将同一页面推送到导航堆栈,对我来说似乎是拼凑而成。

2 个答案:

答案 0 :(得分:0)

  

问题是,当我在运行时设置语言时,翻译扩展标记不会评估新翻译。

您可能需要为TranslationManager使用INotifyPropertychanged接口,当您更改UI区域性时,绑定到索引的所有字符串都会更新。

更多详细信息,请参阅:

Xamarin.Forms change UI language at runtime (XAML)

答案 1 :(得分:0)

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;
    }        
}

以及最初提出的Translator类,但为了清晰起见,在此处通过GetString调用进行了复制:

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));
    }
}

通过以下方式绑定文本:

{i18n:Translate Label_Text}

要触发语言更新,您只需致电:

Translator.Instance.Invalidate()

解决方案来自: https://forums.xamarin.com/discussion/82458/binding-indexername-and-binding-providevalue-in-xamarin-forms