Локализация Silverlight из базы данных, а не resx - PullRequest
2 голосов
/ 28 февраля 2011

У меня есть приложение 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://forums.silverlight.net/forums/p/168712/383052.aspx

1 Ответ

1 голос
/ 04 марта 2011

Хорошо, никто не ответил, и я нашел решение.

Похоже, что вы можете загрузить словарь языка в свои глобальные ресурсы, используя

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}}"/>

Этот метод хорошо работает для нас.

...