Используйте строки в файле.resw непосредственно в XAML

Я знаю, что обычный способ ссылки на локализованные строки из файла.resw будет выглядеть так:

XAML:

<Button x:Uid="ButtonUid" />

Resources.resw:

ButtonUid.Content = "Hello World"

Но возможно ли это сделать так:

XAML (псевдокод):

<Button Content = "$buttonLabel" />

Resources.resw:

buttonLabel = "Hello World"

Причина, по которой я хочу сделать это, как во втором примере, заключается в том, что это приложение, которое я портирую с iOS и Android на WP. Я хотел бы преобразовать файл строк iOS или Android в синтаксис.resw, но не перебирая каждую строку и не добавляя.Content или.Text, или для чего бы то ни было. Есть ли простое решение для этого?

2 ответа

Вы можете использовать CustomXamlResourceLoader:

public class XamlResourceLoader : CustomXamlResourceLoader
{
    private readonly ResourceLoader _loader;

    public XamlResourceLoader()
    {
        _loader = ResourceLoader.GetForViewIndependentUse();
    }

    protected override object GetResource(string resourceId, string objectType, string propertyName, string propertyType)
    {
        return _loader.GetString(resourceId) ?? resourceId;
    }
}

Затем в вашем конструкторе App.xaml.cs:
CustomXamlResourceLoader.Current = new XamlResourceLoader();

И наконец в вашем xaml:
<Button Content = "{CustomResource buttonLabel}" />

Однажды я сделал нечто подобное: мы добавили новые строки в файл строковых ресурсов Android, а затем использовали специальные инструменты сборки, чтобы преобразовать их в форматы iOS и Windows.

Строка Android может выглядеть так:

<string name="Hello">Hello, World!</string>

Наш инструмент преобразует это в строковый ресурс Windows:

<data name="Hello">
  <value>Hello, World!</value>
</data>

Затем добавьте конвертер, который ничего не делает с предоставленным значением, но вместо этого предполагает, что его параметр является идентификатором ресурса:

public sealed class LocalizeConverter : IValueConverter
{
    private static readonly ResourceLoader Loader = ResourceLoader.GetForViewIndependentUse("/Resources");

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        string resourceId = parameter as string;
        return !string.IsNullOrEmpty(resourceId) ? Loader.GetString(resourceId) : DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotSupportedException();
    }
}

Теперь сделайте этот конвертер доступным для вашего XAML, возможно, что-то вроде этого:

<Page.Resources>
    <local:LocalizeConverter x:Key="LocalizeConverter" />
</Page.Resources>

И наконец, установите ваш Button"s Content Свойство следующим образом:

<Button
    Content="{x:Bind Converter={StaticResource LocalizeConverter}, ConverterParameter=Hello, Mode=OneTime}"
/>

Обратите внимание, что мы не предоставляем никакого значения для конвертера. (В WPF я бы создал расширение разметки. К сожалению, эта опция недоступна в UWP, поэтому в качестве альтернативы я предложил эту опцию преобразования без значения.)

Если вы хотите стать еще лучше, подумайте об этом:

<Button
    Content="{x:Bind Language, Converter={StaticResource LocalizeConverter}, ConverterParameter=Hello, Mode=OneWay}"
/>

Это позволяет вам менять язык на лету, если у вас есть ресурсы, локализованные на другие языки. (Заметка Mode=OneWay вместо Mode=OneTime.)

Другие вопросы по тегам