Россия, Тамбов, ТГТУ, 2009 |
Специальные возможности
Подготовка к локализации
Как только ваше приложение было подготовлено к мировому рынку, это означает, что оно может поддержать практически любой язык и региональные установки, которые вы ему передадите, следующий шаг заключается в том, чтобы убедиться, что языкозависимые ресурсы в приложении чётко отделены от HTML, CSS и JavaScript, и размещены там, где их может найти средство загрузки ресурсов Windows (так же упоминаемое как Система управления ресурсами, Resource Management System).
Прежде чем продолжать, вот отличный материал в документации по этой теме: "Подготовка к локализации" (http://msdn.microsoft.com/library/windows/apps/hh967759.aspx), который содержит советы по переводу и другие подробности. Непродуктивно повторять всё это здесь, конечно, поэтому я, вместо этого, хочу разбить руководство на два шага, которые вы можете реализовать для своего приложения и иго языка по умолчанию прежде чем добавлять поддержку дополнительных языков.
Примечание. Загрузчик ресурсов поддерживает разреженную локализацию (sparse localization) для языков, между которыми имеются лишь небольшие различия. Это значит, что при работе с языками, наподобие американского английского (en-US) и британского английского (en-GB), большая часть ресурсов приложения может быть назначена en-US, в то время, как en-GB-ресурсы будут отражать различия, вроде "color" и "colour", "favorite" и "favourite" или наоборот. Так как каждый ресурс разрешается индивидуально, в соответствии с предпочтениями пользователя, приложение, выполняющееся в контексте языка en-GB обнаружит специфические данные, а в противном случае загрузчик использует ресурсы для языка en-US. Существует так же поддержка работы с языковыми исключениями, с помощью ресурсов отмеченных неопределенным тегом und. Смотрите материал "Управление языковыми и региональными параметрами" (http://msdn.microsoft.com/library/windows/apps/Hh967758.aspx), шаг 4 (ближе к концу) и материал "Сопоставление языков" (http://msdn.microsoft.com/library/windows/apps/jj673578.aspx).
Часть 1. Разделение строковых ресурсов
Первый шаг в подготовке к локализации заключается в переносе строк, зависимых от языка или региона, из исходного кода в файлы строковых ресурсов и вставка ссылок на данные файлы там, где это нужно. В следующем разделе мы зададим структуру папок для этих файлов и ресурсов изображений, которые будут использованы в локализованной версии.
Для того, чтобы создать ваш первый файл строковых ресурсов, щёлкните правой кнопкой по вашему проекту в Обозревателе решений Visual Studio, выберите команду Добавить>Создать элемент (Add>New Item), и затем выберите Файл ресурсов (Resources File) (.resjson). Хотя вы можете изменить имя файла, просто оставьте его сейчас в значении по умолчанию resources.resjson. Нажмите Добавить (Add), и файл будет создан в корневом разделе вашего проекта, где он и будет оставаться до Части 2.
С опущенными комментариями, которые находятся в верхней части, этот файл выглядит так:
{ "greeting" : "Hello World!", "_greeting.comment" : "This is a comment to the localizer" }
Как видите, файл – это обычны JSON, где каждое свойство имеет строковой идентификатор и строковое значение. Любой resjson0 файл может иметь столько свойств, сколько нужно.
Очевидна так же и взаимосвязь между двумя вышеприведенными записями. Первая, в форме
<identifier> : <value>
это реальный строковой ресурс, который задает соответствие действительного JSON-идентификатора(пробелы не применяются) строковому значению. Это то, что загрузчик ресурсов использует для замены ссылки на идентификатор строковым значением.
Любая запись, которая начинается с символа подчеркивания, такая, как обычно применяемая
<_identifier.comment> :<value>
игнорируется загрузчиком ресурсов. Подобные записи предоставляют заметки для переводчика, чтобы он полностью понимал, как используется строка, и то, какие её части не следует переводить. Второй необязательный тип записей, это
<_identifier.source> : <value>
который предоставляет исходную строку на языке по умолчанию, что очень полезно для справочных целей.
Если вы хотите взглянуть на более обширные файлы resjson, откройте пример "Ресурсы приложения и локализация" (http://code.msdn.microsoft.com/windowsapps/Application-resources-and-cd0c6eaa) и посмотрите в папку strings для конкретного языка. В файле ja/resources.resjson, например, вы увидите строковые ресурсы вместе с комментариями и исходными текстами записей:
{ "displayName" : "???????? ???? JS SDK ????", "_displayName.source" : "Application Resources JS SDK Sample", "_displayName.comment" : "Don't change 'SDK'", "description" : "???????? ???? JS SDK ????", "_description.source" : "Application Resources JS SDK Sample", "_description.comment" : "Don't change 'SDK'", }
Возвращаясь к вашему собственному приложению и имея новый файл resources.resjson, мы готовы продолжать, выполнять поиск и замену в проекте приложения, искать локализуемые строки, извлекать их в ресурсный файл и заменять их в исходных файлах соответствующими ссылками. Три основных места, которые нам нужно просмотреть, это ваши HTML-файлы, JavaScript-файлы и манифест приложения. Для целей демонстрации, я показал, что я сделал в приложении "Here My Am!", с которым мы работаем на протяжении курса (к нему я добавил файл resources.resjson).
Примечание. CSS-файлы могут содержать страковые литералы в стилях content и quotes; однако, разрешение ресурсов из CSS-файлов для приложений для Магазина Windows в Windows 8 не поддерживается. Локализация в CSS должна быть выполнена с помощью псевдо-селекторов :lang и :-ms-lang.
JavaScript. Начнем с JavaScript, где вам нужно просмотреть код в поиске строковых литералов, включая те, которые выводятся в элемент canvas. В "Here My Am!" я нашёл лишь пару локализуемых строк, а именно, имя папки, используемое в Библиотеке изображений, а так же – заголовок и описание, используемое при форматировании текста для контракта Общий доступ и динамических плиток: (pages/home/home.js):
var folderName = " HereMyAm "; data.properties.title = " Here My Am! "; return "At latitude " + lat + ", longitude " + long return "At (" + lat + ", " + long + ")" А так же команды для раздела Параметры в js/default.js: app.onsettings = function (e) { e.detail.applicationcommands = { "about": { title: "About", href: "/html/about.html" }, "help": { title: "Help", href: "/html/help.html" }, "privacy": { title: "Privacy Statement", href: "/html/privacy.html" } }; WinJS.UI.SettingsFlyout.populateSettings(e); };
Обратите внимание на то, что в home.js строки на английском используются для показа информации об исключениях, но так как они нужны лишь для отладочных целей, их локализовывать не нужно.
После извлечения других строк в файл resources.resjson, мы приводим его к следующему виду, где я использовал обычные комментарии для того, чтобы указать на то, где используется строка. Обратите внимание на то, что я использовал форматную строку при создании описания местоположения для чудо-кнопки Общий доступ и плиток, вместо того, чтобы задавать эту конструкцию в коде (смотрите функцию formatLocation в js/home.js для того, чтобы увидеть, как это используется):
{ // pages/home/home.js "foldername" : "HereMyAm", "share_title" : "Here My Am!", "location_formatShort" : "At (%s, %s)", "_location_formatShort_comment" : "Used to format a short location as in 'At (120, 45)", "location_formatLong" : "At latitude %s, longitude %s", "_location_formatLong_comment" : "Used to format a long location, 'At latitude 120, longitude 45", // default.js // Команды панели параметров "about_command" : "About", "help_command" : "Help", "privacy_command" : "Privacy Statement", }
Настоятельно рекомендую, чтобы вы организовали ваши записи по файлам исходного кода, как здесь, и так же вы можете использовать несколько файлов ресурсов, если хотите, как показано в следующем разделе. Так же будьте осторожны с повторным использованием тех же самых строк, которые появляются в нескольких местах. Если это тот же самый пользовательский интерфейс, отображаемый с тем же самым намерением, то всё нормально, но если контекст использования отличается, лучше дублировать строку, так как на другие языки она может переводиться по-другому. В вышеприведенных ресурсах, обратите внимание на то, что я включил комментарий для location_formatShort, так как слово "At" само по себе, возможно, нуждается в некотором контексте для верного перевода.
Когда строки выделены в виде ресурсов, теперь мы можем использовать загрузчик ресурсов для получения этих строк во время выполнения программы. Это можно сделать двумя способами. Первый – с использованием API WinRT, а именно, Windows.ApplicationModel.Resources.ResourceLoader.getString (http://msdn.microsoft.com/library/windows/apps/windows.applicationmodel.resources.resourceloader.getstring.aspx):
var loader = new Windows.ApplicationModel.Resources.ResourceLoader(); var text = loader.getString('location_formatShort');
или, проще, с использованием функции-оболочки WinJS.Resources.getString (http://msdn.microsoft.com/library/windows/apps/hh701590.aspx):
var text = WinJS.Resources.getString('location_formatShort').value;
Это работает и в веб-контексте, где WinRT недоступна (Смотрите Сценарий 12 примера "Ресурсы приложения и локализация" (http://code.msdn.microsoft.com/windowsapps/Application-resources-and-cd0c6eaa) ). Обратите внимание на то, что getString возвращает объект, который содержит свойство value со строкой, а так же свойство lang и флаг empty, указывающий на то, что ресурс не был найден.
Метод WinJS, который записывается в одну строку, очевидно, полезен в случае наподобие наших команд параметров, так как мы можем вызывать его внутри. Таким образом, в нашем коде мы просто заменяем строковые литералы на вызовы WinJS, как, например, в pages/home/home.js:
data.properties.title = WinJS.Resources.getString('about_command').value;
И так, внутри объекта для команд панели чудо-кнопки Параметры:
"about": { title: WinJS.Resources.getString('about_command').value, href: "/html/about.html" },
Обратите внимание на то, что WinJS, оптимизированный для обычных сценариев, поддерживает загрузку строк лишь на языке пользователя по умолчанию. С другой стороны, класс WinRT ResourceLoader обладает гораздо большей гибкостью и может загружать строки на любом заданном языке. Вам нужно использовать данное API, если ваши нужды превышают то, что предоставляет WinJS.
И это всё, что нужно сделать для JavaScript. Если вы сделали подобные изменения в своем приложение, самое время выполнить команду Построение>Построить решение (Build>Build Solution) в Visual Studio. По этой команде файл ресурсов resources.resjson будет скомпилирован в более эффективный двоичный формат и назван resources.pri, записи, имя которых начинается с символа подчеркивания, отбрасываются. Выполнение периодического построения (без запуска приложения) это хороший подход при работе с ресурсами, благодаря которому вы можете обнаружить любые проблемы в ваших файлах, такие, как дублирование записей или синтаксические ошибки. Затем вы можете запустить приложение для того, чтобы увидеть загрузчик ресурсов в действии – в основном не видя различий между тем, что получилось сейчас, и тем, что было раньше! Не забудьте протестировать все ветви кода, которые были вовлечены в работу, для того, чтобы убедиться, что все строки загружаются соответствующим образом.
Манифест. Обратимся теперь к манифесту, где всё даже проще, так как здесь не используется код. Текстовые фрагменты, которые могут нуждаться в локализации, это следующие:
- Отображаемое имя (display name), Описание (description) и Краткое имя (short name) (для плиток) на закладке Интерфейс приложения (Application UI)
- Любые текстовые описания для конкретных записей на закладке Объявления (Declarations).
- Отображаемое имя пакета (package display name) на закладке Упаковка (Packaging). (Следует менять Имя пакета (package name), только если вы собираетесь отправить приложение в Магазин Windows под другим именем на другие рынки, в таком случае это будет совсем другой пакет).
- Возможно, некоторые URI на закладке URI содержимого (Content URI).
Пока мы работаем с манифестом, обратите внимание на параметр Язык по умолчанию (Default Language) на закладке Интерфейс приложения(Application UI). Это то, что определяет язык приложения по умолчанию или резервный (fallback) язык, если пользователь запускает приложение с языком, который не поддерживается в ресурсах. Мы так же вернемся к изображениями в манифесте в следующем разделе.
Найдя все строки в манифесте, извлеките их в файл resources.resjson, задав им подходящие идентификаторы. Опять же, если у вас есть какие-то сроки в манифесте, которые соответствуют похожим строкам где-то еще в приложении, тщательно оцените их на предмет того, можно ли использовать для них те же ресурсы. Если вы сомневаетесь, храните их раздельно, так как подобная избыточность незначительна. В случае с приложением "Here My Am!", отображаемое имя приложения и строка, используемая для заголовка главной страницы выглядят одинаково и используются похожим образом, поэтому данные параметры могут ссылаться на один и тот же ресурс.
Для того, чтобы сослаться на ресурсы в манифесте, используйте синтаксис ms-resource:<identifier>. Например, я поместил значение из параметра Интерфейс приложения>Отображаемое имя (Application UI>Display Name) в файл ресурсов и назвал его app_title, в итоге, в данном поле редактора манифеста я просто ввожу ms-resource:app_title. То же самое я делаю для описания и отображаемого имени пакета.
Как только вы выполнили эти изменения, запустите приложение и убедитесь в том, что текст на плитках, если вы используете его, отображается верно. Вы можете временно установить параметр Интерфейс приложения>Показывать имя (Application UI>Show Name) в значение Все значки(All Logos) и проверить, но не забудьте вернуть всё обратно!
Врезка: Локализованные строки в полезных данных XML для плиток и всплывающих уведомлений
Как описано в материале "Глобализация и специальные возможности для уведомлений на плитках и всплывающих уведомлений" (http://msdn.microsoft.com/library/windows/apps/Hh831183.aspx), полезные данных XML для плиток и всплывающих уведомлений испльзуют синтаксис ms-resource: для идентификации строковых ресурсов в текстовых элементов. Это вызовет механизм поиска загрузчика ресурсов при выводе плитки, и это работает независимо от того, было ли отправлено уведомление локально, получено с веб-сервиса или принято в виде push-уведомления. Веб-сервисам лишь нужно использовать соответствующие идентификаторы ресурсов приложения.
Веб-сервис так же может напрямую отправлять локализованные обновления плиток. В таком случае приложение обычно присоединяет строку запроса в URI сервиса, отражающую необходимый язык, обновляя при необходимости эти параметры при изменении языка (смотрите "Чистовая отделка локализации" для того, чтобы узнать подробности). Так же приложение может скомбинировать это с использованием региональных веб-сервисов, что помогает в локализации данных обновлений.
HTML. Последнее место, где нам нужно искать строки, это наш HTML-код, который я оставил напоследок, так как работа с ним сложнее, чем другая. Работая с HTML нужно внимательно очистить разметку от любых заданных в ней текстов, которые видимы в пользовательском интерфейсе. Проверьте основное содержимое таких элементов, как p, h1, span, div, button, option, и так далее, так же, как и значения атрибутов title, alt, aria-label, и так далее. Кроме того, посмотрите в элементах управления WinJS, наподобие панели приложения и всплывающих элементов на предмет любых встроенных в них URI, которые вам хотелось бы локализовать, включая ссылки на сервисы, которые вы используете и на содержимое, которое вы показываете в iframe. Обратите внимание, что элементы title в заголовке страницы не отображаются, поэтому не нуждаются в локализации.
В приложении "Here My Am!" я обнаружил множество строк в pages/html/home.html, которые я выделил:
<header id="header" aria-label="Header content" role="banner"> <section id="section" aria-label="Main content" role="main"> <div id="photoSection" class="subsection" aria-label="Photo section"> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle">Here My Am! (8)</span> </h1> <h2 class="group-title" role="heading">Photo</h2> <img id="photo" class="graphic" src="/images/taphere.png" alt="Tap to capture image from camera" role="img" /> <div id="locationSection" class="subsection" aria-label="Location section"> <h2 class="group-title" role="heading">Location</h2> <div id="floatingError" class="win-type-x-large"> Unable to obtain geolocation; check <br />permissions and use the app bar to try again. </div> <div id="retryFlyout" data-win-control="WinJS.UI.Flyout" aria-label="Trying geolocation" data-win-options="{anchor: 'mapDiv', placement: 'bottom', alignment: 'center'}"> <div class="win-type-large">Attempting to obtain geolocation...</div> </div>
Где я так же заметил, что мне нужно локализовать изображение taphere.png, так как оно содержит текст, но это в следующем разделе. В default.html, я так же обнаружил подписи и всплывающие подсказки в атрибутах data-win-options команд Панели приложения (для краткости я опустил часть разметки):
<div id="appbar" data-win-control="WinJS.UI.AppBar" data-win-options=""> <button data-win-options="{id:'cmdPickFile', label:'Load picture', icon:'browsephotos', section:'global', tooltip:'Load a picture through the file picker'}"> </button> <button data-win-options="{id:'cmdRecentPictures', label:'Recent pictures', icon:'pictures', section:'global', tooltip:'Browse recent pictures taken in the app'}"> </button> <button data-win-options="{id:'cmdRefreshLocation', label:'Refresh location', icon:'globe', section:'global', tooltip:'Refresh your location'}"> </button> </div>
Совет. Подготавливаясь к локализации, выясните, имеют ли значки на Панели приложения универсальное значение. Если нет, их так же нужно локализовать. К счастью, значения значков имеют строковой формат и могут быть локализованы, в таком случае их нужно воспринимать так же, как подписи и всплывающие подсказки.
Другие файлы в приложении, которые требуют внимания, это все файлы в папке HTML, которые используются для панели чудо-кнопки Параметры. Работая с подобными командами, будьте особенно внимательны с короткими заголовками подписей, которые могут быть элементами div среди другого кода. Не упустите ничего!
Как только вы найдете строки, скопируйте их, как и ранее, в resources.resjson. Работы по копированию и вставке может быть довольно много, поэтому соберитесь с духом и сделайте это. В подобных строках может быть и HTML – он просто добавляется в разметку и выводится так же, как если бы вы присоединили его к свойству наподобие innerHTML, но не включайте туда окружающие теги (скоро они нам понадобятся). Например, в html/about.html у меня есть множество элементов p с текстом:
<p>Here My Am!<br />Version 1.0.0.0<br /></p>
Для данного элемента я создал такую стоку в файле ресурсов (без тега p):
about1" : "Here My Am!<br />Version 1.0.0.0<br />",
А теперь самое интересное: как сослаться на строковой ресурс в разметке. Если вы немного подумаете, то окажется, что нам может понадобиться запустить некий код, который просмотрит разметку и заменит ссылки, которые мы сделали, на соответствующие строки ресурсов. Хм. Не видели ли мы что-то подобное раньше? Да, на самом деле. Работая с элементами управления, мы добавляли в разметку атрибуты data-win-control и использовали WinJS.UI.processAll или WinJS.UI.process для выполнения кода по созданию экземпляров элементов управления. У нас есть нечто подобное и для ресурсов: атрибут data-win-res и WinJS.Resources.processAll, последний должен быть вызван в методе ready каждой страницs или где-нибудь еще при загрузке HTML-содержимого, например, для Панели приложения, например, в обработчике активации приложения после WinJS.UI.processAll (то есть, экземпляры элементов управления уже будут созданы).
Вот, что нужно сделать в разметке:
-
Заменить атрибуты и их строковые значения на это исходное имя атрибута, а <identifier> соответствует желаемой строке в файле ресурсов и заключен в одинарные кавычки.
data-win-res="{<attribute> : '<identifier> '}" где <attribute>
-
Если есть множество атрибутов в одном и том же элементе, вы можете разделить каждую пару ' с помощью запятой.
<attribute> :'<identifier>
- Там, где строка находится в теге, мы используем data-win-res с эквивалентным именем атрибута, например, textContent для элементов div, p, или span. Если строка содержит разметку, используйте вместо этого innerHTML, но только по необходимости, так как textContent гораздо быстрее.
-
Для атрибутов с дефисами, наподобие aria-label, используйте синтаксис в значении data-win-res, используя одинарные кавычки вокруг <attribute> . С помощью такого подхода можно скомбинировать локализацию и реализацию специальных возможностей.
{attributes: {'<attribute> ' :'<identifier> '}}
-
Для свойств элементов управления WinJS, которые обычно отображаются в data-win-options, разместите их в data-win-res с использованием синтаксиса Несколько свойств, опять же, разделяются запятыми во внутренних фигурных скобках { }.
{winControl: {<property> : '<identifier> '}}.
Вот примеры модификации разметки, приведенной ранее:
Исходная разметка | Измененная разметка |
---|---|
<img id="photo" class="graphic" src="/images/taphere.png" alt="Tap to capture image from camera" role="img" /> | <img id="photo" class="graphic" src="/images/taphere.png" data-win-res="{alt: 'photo_alt'}" role="img" /> |
<span class="pagetitle">Here My Am! (8)</span> | <span class="pagetitle" data-win-res="{textContent : 'app_title'}"></span> |
<div id="locationSection" class="subsection" aria-label="Location section"> | <div id="locationSection" class="subsection" data-win-res="{attributes: {'aria-label' : 'aria_location'}}" > |
<div id="floatingError" class="win-type-x-large"> Unable to obtain geolocation; check<br />permissions and use the app bar to try again. | <div id="floatingError" class="win-type-x-large" data-win-res="{innerHTML : 'error_obtaingeoloc'}"> |
<button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdPickFile', label:'Load picture', icon:'browsephotos', section:'global', tooltip:'Load a picture through the file picker'}"> | <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdPickFile', icon:'browsephotos', section:'global'}" data-win-res="{winControl: {label : 'appbar_label1', tooltip : 'appbar_tooltip1'}}"> |
Когда WinJS.Resources.processAll обходит DOM, он, на самом деле, не удаляет атрибуты data-win-res attributes; он лишь обрабатывает их значения и добавляет к элементам другие атрибуты, которые содержат строковые ресурсы. Преимущество подобного подхода заключается в том, что последующий вызов processAll пройдёт по DOM и обновит все эти строки. Это означает, что если вы обрабатываете событие WinJS.Resources. oncontextchanged, которое сообщает вам об изменении языка, вы можете снова вызвать processAll и ваш пользовательский интерфейс будет отображен с использованием нового языка! Мы добавим этот код позже, когда мы добавим в приложение "Here My Am!" еще несколько языков.
Это так же означает, что если вы хотите произвести привязку данных WinJS, используя строки, которые соответствуют вашим ресурсам, просто включите атрибуты data-win-bind внутрь этих строк, присвойте строки свойствам элементов innerHTML в data-win-res, и затем не забудьте вызвать WinJS.Resources.processAll перед вызовом WinJS.Binding.processAll. Это показано в Сценарии 8 примера "Ресурсы приложения и локализация" (http://code.msdn.microsoft.com/windowsapps/Application-resources-and-cd0c6eaa) (html/scenario8.html and js/scenario8.js):
HTML: <p id="messageCount" data-win-res="{innerHTML: 'scenario8MessageCount'}"> Resources: "scenario8MessageCount" : "You have <span data-win-bind=\"innerText:count\"></span> message(s)",
И с помощью этого (исключая последующей врезки, которую я добавил ниже), мы готовы к следующему шагу, к работе с графическими ресурсами и к локализации всего того содержимого, которое мы извлекли.
Врезка: Строковые ресурсы во всплывающих элементах настройки параметров
Во всем этом та часть разметки, которая предназначена для HTML-страниц всплывающих элементов для настройки параметров, а именно, about.html, help.html, и privacy.html в папке проекта HTML, вызывает наибольшую сложность. Эти страницы не загружаются до тех пор, пока не будет активирована чудо-кнопка Параметры, и так как это происходит в WinJS, мы можем использовать событие всплывающего элемента beforeshow для вызова WinJS.Resources.processAll для разметки всплывающего элемента. Для того, чтобы перехватить это событие, я добавил onbeforeshow : beforeShow в каждую строку data-win-options и затем данный код с тегом script в конце элемента body:
function beforeShow() { WinJS.Resources.processAll(); } beforeShow.supportedForProcessing = true;
Последняя строка здесь необходима, так как WinJS вызовет WinJS.UI.processAll когда страница будет загружена. В любом случае, это хорошо работает для строковых ресурсов, с одним исключением. В privacy.html, (подробнее об этом – в Главе 2 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), я использовал iframe для загрузки удаленной страницы с соглашением о конфиденциальности. Так как и она должна быть локализована, я разместил URI в строковые ресурсы и попытался загрузить его как и прочие строки:
<!-- Это не работает --> <iframe data-win-res="{src : 'privacy_URI'}" height="600"></iframe>
Однако это привело к исключению в WinJS.Resources.processAll, которое сообщало о том, что что-то не было помечено как supportedForProcessing. И что? Только функции так маркируют, и я не мог думать о том, что это относится и к iframe. Оказалось, что элементы iframe специально блокируются в методах WinJS processAll , как и немаркированные функции. В результате, вы просто не можете использовать data-win-res с iframe!
К счастью, простое решение заключается в том, чтобы назначить элементу iframe id (privacyFrame), загрузить строку самостоятельно в обработчике beforeshow и затем установить атрибут iframe.src:
document.getElementById("privacyFrame").src = WinJS.Resources.getString('privacy_URI').value;