Pull to refresh

Копаемся в исходниках Windows 8 Metro Weather

Reading time 7 min
Views 11K
После установки Windows 8 (64bit + VS2011) и ознакомления с новым интерфейсом Metro первым делом захотелось переключить температуру из градусов по фаренгейту в градусы по цельсию. Это подтолкнуло к копанию в исходниках, а затем и к русификации приложения.

О чем статья:
  • Где лежит и из чего состоит установленное приложение
  • Как переключить фаренгейты в цельсии
  • Как установленное приложение перенести в VS2011 и запустить в отладчике
  • Добавление кнопки в приложение
  • Частичная и полная русификация





Где лежит


Для тех кто не смотрел build или не обратил внимание, полный путь к папке с приложением: C:\Program Files\Applications\microsoft.weather_1.0.0.26_neutral_neutral_8wekyb3d8bbwe

Чтобы увидеть папку Applications нужно в проводнике открыть Program Files и на вкладке View поставить галочку Hidden items. Просто так попасть в папку Applications не получится, для этого понадобится добавить себе разрешения, для этого в свойствах этой папки идем на вкладку Security.
Приложение написано на javascript и состоит из набора файлов форматов .css, .html, .js, файла ресурсов .pri, сертификата подписи .p7x, и набора картинок и видеофайлов для фона

Переключаем фаренгейты в цельсии


Чтобы переключить фаренгейты в цельсии мне пришлось залезть в исходники. Тем кто еще не успел туда залезть для этого достаточно нажать Win + C выбрать пункт Settings и в появившейся панельке справа нажать Weather preferences и выбрать привычные цельсии.

Запускаем приложение в Visual Studio 2011


Чтобы это сделать мне понадобилось создать в VS пустой javascript проект. Затем взглянув на структуру проекта изменил название default.html на defaultHost.html, и перенес содержимое файла. Потом пришлось добавить в проект картинки, видео, таблицы стилей, js скрипты и скопировать содержимое AppxManifest.xml в package.appxmanifest. Чтобы из Metro не пропала “плитка” установленного приложения достаточно изменить в этом файле Package Name c Microsoft.Weather на другое.
В VS2010 добавить текстовые ресурсы можно было через меню в свойствах проекта, а здесь достаточно добавить в проект новый файл Resources File (.resjson). После добавления открываю файл и вижу закомментированое описание об использовании текстовых ресурсов. Вот вроде бы и все. Можно запускать приложение в Debug или Release, ставить точки останова и изучать как оно работает.

Добавим кнопку и подпишемся на клики


Взглянув на defaultHost.html решил поиграться с кодом и добавить свою кнопку с обработчиком события и своей картинкой.
Кнопку поставил на appbar, для этого скопировал код кнопки Remove City и вставил рядом. Вот что получилось:
<button id="ruCulture" class="win-command" ><br/>
                <span class="win-spritestates win-commandicon win-large ruicon"></span> <br/>
                <span id="cultureText" class="win-label" data-win-res="textContent: ruCulture">ru-RU</span><br/>
</button>

Теперь надо добавить обработчик нажатия, для этого в defaultNew.js нахожу добавление обработчика нажатия на Remove City и вставляю строчку кода:
id("ruCulture").addEventListener("click", switchCulture);

Функция id обёртка для document.getElementById, её можно найти в currentCityControl.js. switchCulture моя функция которая будет переключать язык локализации, об этом ниже в статье.

Частичная и полная русификация


Что значит частичная? Это значит просто смена локали на ru-RU в запросе к серверу погоды, и соответственно получение от сервера метеосводки на русском языке. Приложение остается на своем языке. А с добавлением текстовых ресурсов на русском языке получаем полную русификацию.

Для себя поставил задачу сделать кнопку переключения локали с ru-RU на fr-FR и сохранение этой настройки, чтобы после перезапуска приложение брало данные о погоде ня языке сохраненной локали.

В файле data.js есть строчка

var culture = R.getString("/webservice/culture");

где R из defaultHost.js R = new Windows.ApplicationModel.Resources.ResourceLoader();

В переменную culture заносится текущая локаль из файла ресурсов. Пишу функцию getCulture(), а эту строчку меняю на:
var culture = getCulture();


Затем иду в defaultHost.js и добавляю culture:

    WinJS.Namespace.define("Weather.Settings", {<br/>
        hourly: ApplicationData.current.localSettings.values["hourlydaily"] == "h",<br/>
        celsius: ApplicationData.current.localSettings.values["temp"] == "c",<br/>
        setForecastHourly: setForecastHourly,<br/>
        setForecastDaily: setForecastDaily,<br/>
        setUnitCelsius: setUnitCelsius,<br/>
        setUnitFahrenheit: setUnitFahrenheit,<br/>
        // Вот здесь добавляю<br/>
        culture: ApplicationData.current.localSettings.values["culture"]<br/>
    });<br/>
 <br/>
// После тут же сразу поставим локаль<br/>
Weather.Settings.culture = getCulture();


В конец defaultHost.js вставляю свои функции

function getCulture() {<br/>
if (!Weather.Settings.culture)<br/>
{<br/>
       // если уже есть сохраненная настройка загрузим иначе ru-RU <br/>
var idc = Windows.Storage.ApplicationData.current.localSettings.values["culture"];<br/>
if (idc) {<br/>
setCulture(idc);<br/>
} else {<br/>
setCulture("ru-RU");<br/>
}<br/>
}<br/>
return Weather.Settings.culture;<br/>
}<br/>
function setCulture(culture1) {<br/>
    if (Weather!==undefined) {<br/>
        Weather.Settings.culture = culture1;<br/>
        Windows.Storage.ApplicationData.current.localSettings.values["culture"] = culture1;<br/>
    }else {<br/>
            var idc = Windows.Storage.ApplicationData.current.localSettings.values["culture"];<br/>
            if (idc) {<br/>
                Weather.Settings.culture = idc;<br/>
            } else {<br/>
                Weather.Settings.culture = "ru-RU";<br/>
            }<br/>
    }<br/>
}


Для удобства отладки в defaultHost.html добавил div для вывода отладочной информации, а в defaultHost.js функцию deb(). Эту функцию можно вызвать из любого места скрипта и вывести любую информацию.

function deb(stok) {<br/>
var deb = document.getElementById("debugText");<br/>
if (deb) {<br/>
    deb.innerText = stok;<br/>
}<br/>
}


Осталось сделать переключение локали с сохранением настройки
Кнопка уже добавлена, нарисую для нее значек. В файле Weather_Commands_PNG_STRIP_40x.png хранятся все значки кнопок. Открываю файл и увеличиваю размер изображения вниз, рисую кнопки для разных состояний своей кнопки.
Чтобы значек кнопки отображался добавляю настройку стиля в defaultHost.css

 <br/>
button .ruicon<br/>
{<br/>
    background-position: 0px -280px;<br/>
}<br/>
 <br/>
button:active .ruicon<br/>
{<br/>
    background-position: -80px -280px;<br/>
}<br/>
 <br/>
button:disabled .ruicon<br/>
{<br/>
    background-position: -120px -280px;<br/>
}


Кнопка есть, значок на ней есть, на click по кнопке подписался осталось добавить функцию:
    function switchCulture(e) {<br/>
if (getCulture()=="ru-RU") {<br/>
     setCulture("fr-FR");<br/>
     } else {<br/>
     setCulture("ru-RU");<br/>
     }<br/>
        var culture = id("cultureText");<br/>
        if (Weather.Settings.culture) {<br/>
            culture.innerText = Weather.Settings.culture;<br/>
        }<br/>
        // TO-DO: <br/>
        // сразу перегрузим метеосводку на новом языке<br/>
        // попытка в лоб - не работает - не разобрался<br/>
        mainData.refresh(true).then(function () { });<br/>
        updateAllTiles();<br/>
    }


Запускаю приложение в Release, жму кнопку, ставится русская локаль. Останавливаю приложение, запускаю еще раз и приложение грузит погоду на родном языке. Грузит кстати с weather.service.msn.com

Полная русификация приложения через ресурсы


Прогноз уже на русском, осталось перевести интерфейс программы.
Metro приложение определяет локальные установки языка и в зависимости от этого загружает текстовые ресурсы. Добавляю в проект папку strings в нее файл resources.resjson и папку ru-RU с таким же файлом. Содержание файла:

{<br/>
"Add" : "Добавить",<br/>
"Pin" : "Закрепить",<br/>
"CurrentCitySearch" : "Поиск моего города",<br/>
"Tomorrow":"Завтра",<br/>
"Unpin":"Открепить",<br/>
"CurrentCityFound":"Мой город найден",<br/>
"Weather":"Погода",<br/>
"Description":"Погода",<br/>
"GatheringInfo":"Загружаю свежую метеосводку",<br/>
"PinCity":"PinCity",<br/>
"RemoveCity":"Удалить",<br/>
"CurrentCity":"Мой город",<br/>
"AddCity":"Добавить город",<br/>
"SummaryView":"По дням",<br/>
"Hourly":"По часам",<br/>
"EnterCity":"Введите город",<br/>
"AddCityError":"Ошибка добавления города",<br/>
"MaxCities":"Максимум городов",<br/>
"Preferences":"Настройки","Temperature":"Температура",<br/>
"Celsius":"Цельсий",<br/>
"Fahrenheit":"Фаренгейт",<br/>
"ruCulture":"Язык",<br/>
"debugText":"Отладка",<br/>
"LastUpdated" : "Обновлено <span id='lastUpdated'></span>.",<br/>
"Wind" : "Ветер",<br/>
"UVIndex" : "УФ индекс",<br/>
"Today" : "Сегодня",<br/>
"SplashScreenImage" : "Заставка",<br/>
"Search" : "Поиск",<br/>
"ResultsFor" : "Данные для",<br/>
"PercChanceOfRain" : "<span data-win-bind='innerText:precip'></span> возможность дождя",<br/>
"Low" : "Минимум",<br/>
"Humidity" : "Влажность",<br/>
"High" : "Максимум",<br/>
"FeelsLike" : "По ощущениям",<br/>
"CurrentCondition" : "Сейчас",<br/>
"ChanceOfRain" : "Возможен дождь",<br/>
"NetworkConnection" : "Не могу получить прогноз. Проверьте наличие интернета.",<br/>
"CannotRetrieveData" : "Не могу извлечь данные"<br/>
}


Запускаю приложение и Weather превращается в Погоду!
Tags:
Hubs:
+50
Comments 22
Comments Comments 22

Articles