简体   繁体   English

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

[英]Change language runtime with wrapped language resources Xamarin Forms

We are developing several mobile apps, with Common .NET Standard library between them, which holds the common functionallity. 我们正在开发几个移动应用程序,它们之间具有Common .NET Standard库,该库具有通用功能。 (MVVM) The Common project has a TranslationManager Class, and a Resource file, which holds the common translations. (MVVM)Common项目具有一个TranslationManager类和一个Resource文件,其中包含公共翻译。 TranslationManager uses constructor injection, to inject the app specific translation resources. TranslationManager使用构造函数注入,以注入应用程序特定的翻译资源。

    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. 在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 Usage seem to be like: XAML用法似乎是这样的:

  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. 提高使用null参数更改的属性会刷新视图上的绑定,但不会影响MarkupExtensions。

I do not want to push the same page to the navigation stack, it seems patchwork for me. 我不想将同一页面推送到导航堆栈,对我来说似乎是拼凑而成。

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

More detailed info, please refer to: 更详细的信息,请参考:

Xamarin.Forms change UI language at runtime (XAML) Xamarin.Forms在运行时(XAML)更改UI语言

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: 这是最初提出的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));
    }
}

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 : //forums.xamarin.com/discussion/82458/binding-indexername-and-binding-providevalue-in-xamarin-forms

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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