Локализация Silverlight из базы данных, а не resx
У меня есть приложение Silverlight 4 OOB, которое нуждается в локализации. В прошлом я использовал обычный маршрут resx, но меня попросили следовать архитектуре существующего приложения winforms.
Все строки в настоящее время хранятся в базе данных - я использую веб-сервис, чтобы снять их и записать в локальную базу данных Effiproz Isolated Storage. При входе в систему я загружаю объект Dictionary со строками языка для языка пользователя. Это отлично работает.
Однако я хочу автоматизировать локализацию пользовательского интерфейса (приложение WinForms делает это следующим образом): перебрать все элементы управления на странице и найти любые текстовые блоки - если есть текстовое свойство, я заменяю его локализованной версией. Если текст не найден, я пишу строку в базу данных для локализации.
Это работает нормально на простых формах, но как только у вас появятся расширители / средства просмотра прокрутки и элементы управления содержимым, парсер VisualTree не возвращает дочерние элементы элементов управления, поскольку они не обязательно видны (см. Мой код ниже). Это известная проблема, которая мешает моей попытке автоматизации.
Мой первый вопрос: есть ли способ автоматизировать это при загрузке страницы, просматривая сложные (невизуальные) элементы и просматривая значение в словаре?
Мой второй вопрос: если нет, то лучший способ справиться с этим - это загрузить строки в словарь ресурсов приложения и изменить все мои страницы, чтобы ссылаться на него, или я должен посмотреть на создание файлов resx, либо на сервере (и упакуйте его в приложение как обычно) или на клиенте (у меня есть загруженные строки, могу ли я создать и загрузить файлы resx?)
Спасибо за любые указатели.
Вот мой существующий код, который не работает со свернутыми элементами и сложными элементами управления содержимым:
public void Translate(DependencyObject dependencyObject)
{
//this uses the VisualTreeHelper which only shows controls that are actually visible (so if they are in a collapsed expander they will not be returned). You need to call it OnLoaded to make sure all controls have been added
foreach (var child in dependencyObject.GetAllChildren(true))
{
TranslateTextBlock(child);
}
}
private void TranslateTextBlock(DependencyObject child)
{
var textBlock = child as TextBlock;
if (textBlock == null) return;
var value = (string)child.GetValue(TextBlock.TextProperty);
if (!string.IsNullOrEmpty(value))
{
var newValue = default(string);
if (!_languageMappings.TryGetValue(value, out newValue))
{
//write the value back to the collection so it can be marked for translation
_languageMappings.Add(value, string.Empty);
newValue = "Not Translated";
}
child.SetValue(TextBlock.TextProperty, newValue);
}
}
Тогда я попробовал 2 разных подхода:
1) Сохраните строки в обычном объекте словаря. 2) Сохраните строки в обычном объекте словаря и добавьте его в приложение как ресурс, после чего вы можете ссылаться на него как
TextBlock Text="{Binding Path=[Equipment], Source={StaticResource ResourceHandler}}"
App.GetApp.DictionaryStrings = new AmtDictionaryDAO().GetAmtDictionaryByLanguageID(App.GetApp.CurrentSession.DefaultLanguageId);
Application.Current.Resources.Add("ResourceHandler", App.GetApp.DictionaryStrings);
http://http//forums.silverlight.net/forums/p/168712/383052.aspx
1 ответ
Итак, никто не ответил на это, и я нашел решение.
В основном кажется, что вы можете загрузить языковой словарь в свои глобальные ресурсы, используя
Application.Current.Resources.Add("ResourceHandler", App.GetApp.DictionaryStrings);
<TextBlock Text="{Binding [Equipment], Source={StaticResource ResourceHandler}}" />
а затем получить к нему доступ, как обычный StaticResource. У нас есть требование записать все наши отсутствующие строки в базу данных для перевода - по этой причине я решил использовать конвертер, который вызывает метод расширения Localize (так что это можно сделать для любой строки в коде), который затем просматривает Строка в словаре (не ресурс) и может что-то с ним сделать (записать в локальную БД), если она не существует.
Text="{Binding Source='Logged on User', Converter={StaticResource LocalizationConverter}}"/>
Этот метод работает нормально для нас.