Используйте строки в файле.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
.)