Устройство расширения

Эта статья нуждается в редакционном обзоре. Как вы можете помочь.

Файл install.rdf

В предыдущем разделе мы начали рассматривать содержимое расширения "Hello World". Теперь мы рассмотрим его файлы и код, начиная с файла "install.rdf". Вы можете его открыть любым текстовым редактором.

Файл подготовлен с применением специальной разновидности XML, под названием RDF. RDF использовался как основной механизм хранения для Firefox, но сейчас заменяется упрощённой системой баз данных. Далее в учебнике мы рассмотрим обе эти системы хранения данных.

Теперь давайте взглянем на важные части этого файла.

<em:id>helloworld@xulschool.com</em:id>

Это уникальный идентификатор расширения. Firefox-у он нужен, чтобы отличать ваши расширения от других расширений, поэтому надо, чтобы у вас был уникальный ID.

Есть два принятых стандарта для идентификаторов дополнений. Одним из них является формат адреса электронной почты, как в примере "Hello World", в котором должно быть что-то вроде <название-программы>@<ваш-домен>. Другой обычной практикой является использование порождённой строки UUID, повторение которой крайне маловероятно. В Unix-системах, в командной строке есть инструмент под названием uuidgen, порождающий новые UUID-строки. Для всех других платформ также есть такие загружаемые инструменты, порождающие UUID. Окружающие скобки - это просто обозначение и это обычная практика. Пока ваш идентификатор сколь-нибудь уникален, то можно выбрать любую форму.

<em:name>XUL School Hello World</em:name>
<em:description>Welcome to XUL School!</em:description>
<em:version>0.1</em:version>
<em:creator>Appcoast</em:creator>
<em:homepageURL>https://developer.Mozilla.org/en/XUL_School</em:homepageURL>

Это данные, отображаемые до и после установки расширения и которые можно увидеть в панели управления дополнениями. Помощники и переводчики могут добавить много других тегов. Все подробности смотрите в полной спецификации файла install.rdf.

Так как расширения могут быть переведены на несколько языков, часто необходимо перевести описание расширения или, даже, его название. Локализованные описание и название могут быть вписаны с помощью следующего кода:

<em:localized>
  <Description>
    <em:locale>ru-RU</em:locale>
    <em:name>Школа XUL Привет мир</em:name>
    <em:description>Добро пожаловать в школу XUL!</em:description>
  </Description>
</em:localized>

Строчка локали ru-RU указывает, что это русская (ru) локализация для России (RU). Вы можете добавить столько разделов <em:localized>, сколько вам нужно. Для Firefox 2, локализация этого файла немного сложнее. Мы позже в этом разделе ещё обсудим локализацию.

<em:type>2</em:type>

Это указывает, что устанавливаемое добавление является расширением. Вы можете прочитать о различных возможных типах в соответствующем разделе спецификации файла install.rdf.

<em:targetApplication>
  <Description>
    <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
    <em:minVersion>4.0</em:minVersion>
    <em:maxVersion>10.*</em:maxVersion>
  </Description>
</em:targetApplication>

Этот узел определяет целевое приложение и его целевые версии. В частности здесь указан интернет-обозреватель Firefox, начиная с 4-й и до 10-ых версий. Указанный UUID является уникальным идентификатором Firefox. Другие Mozilla и основанные на Mozilla приложения, такие как Thunderbird и Seamonkey имеют свои собственные UUID. У вас может быть расширение, работающее в нескольких приложениях и версиях.  Например, если вы создаёте расширение к Firefox, то, как правило, достаточно минимума усилий, чтобы перенести его в SeaMonkey, имеющее сходные характеристики и пользовательский интерфейс.

Минимум и максимум определяют диапазон версий, дозволительный для установки расширения. Вот ещё ссылка о формате указания версий. Если приложение или диапазон версий не совпадают, то пользователю не будет разрешено установить расширение или расширение будет установлено в отключённом состоянии. Пользователи могут отключить проверку версий в настройках интернет-обозревателя или путём установки дополнений через Докладчик о совместимости дополнений (Add-on Compatibility Reporter). Начиная с Firefox 11, дополнения по умолчанию будут совместимы, и Firefox в основном будет игнорировать диапазон версий. Всё-же рекомендуется всегда проверять дополнения с каждой новой версией Firefox.

Это информация, нужная Firefox и другим приложениям Mozilla для установки дополнения. Любые ошибки или отсутствие информации приведут к сбою процесса установки или установке расширения в выключённом состоянии.

Файл chrome.manifest

Хром (Chrome) - это набор элементов пользовательского интерфейса окна приложения, находящихся за пределами области содержимого окна. Панели инструментов, строки меню, индикаторы прогресса выполнения и заголовки окон - всё это примеры элементов, обычно являющихся частью Хрома.

Взято из Регистрации Хрома.

В двух словах, хром - это всё, что вы видите в Firefox. Все окна Firefox можно рассматривать как состоящие из двух частей: (1) хром, (2) область возможного содержимого (то, что показывают веб-страницы во вкладках Firefox). Такие окна как "окно загрузок" - это чистый Хром.  Большая часть кода расширения находится в папке "хром", как и в примере "Hello World".

Как мы видели в структуре каталогов распакованного расширения, Хром состоит из 3 разделов: content (содержание), locale (локаль, язык) и skin (тема). Эта троица необходима для большинства расширений. Если мы откроем файл chrome.manifest (опять же, сгодится любой текстовый редактор), то увидим, что указаны эти 3 секции:

content   xulschoolhello              content/
skin      xulschoolhello  classic/1.0 skin/
locale    xulschoolhello  en-US       locale/en-US/

Файл chrome.manifest говорит Firefox, где искать файлы Хрома. Текст расположен вразрядку, чтобы выглядел как таблица, но это не обязательно. Синтаксический анализатор (парсер, parser) игнорирует повторение пробелов.

Первое слово в строке говорит Firefox, что именно объявляется (содержание, скин, локаль языка или другое, о чём будет рассказано позже).  Второе - это название пакета, о котором мы скоро расскажем.

У скина и языков есть третье значение для указания, какой именно язык или какой именно скин они расширяют. Может быть несколько скинов и языков, касающихся различных других скинов и языков. Обычно указывают одну запись для глобального скина (classic/1.0) и несколько записей для языковых пакетов, по одному для каждого перевода. Наконец, последним указано расположение в файловой системе.

В файл chrome.manifest могут быть внесены некоторые дополнительные параметры. Они описаны на странице Регистрации Chrome. Примечательно, мы может включить записи, особенные для операционных систем. Это важно, потому что внешний вид браузера отличается в разных операционных системах., Если наше расширение должно выглядеть по-разному в разных ОС, то мы можем изменить файл манифеста, например, таким образом:

content   xulschoolhello              content/
skin      xulschoolhello  classic/1.0 skin/unix/
skin      xulschoolhello  classic/1.0 skin/mac/ os=Darwin
skin      xulschoolhello  classic/1.0 skin/win/ os=WinNT
locale    xulschoolhello  en-US       locale/en-US/

Так, мы можем задать отдельные темы оформления для Windows, Mac OS X, и Linux (а также других Unix-систем), каждая из которых определена в отдельный каталог. Так как большинство других систем на основе Unix, то тема "Unix" указывается по умолчанию, без флагов.

Хром

Как сказано выше, Хром состоит из 3 разделов: содержание (контент), язык (локаль) и тема (скин). Содержание - это важнейший раздел, содержащий в себе пользовательский интерфейс (XUL) и скрипты (JS - JavaScript). Раздел Скин содержит файлы, определяющие большую часть внешнего вида пользовательского интерфейса (с помощью CSS и изображений, как у веб-страниц). Раздел Язык содержит все тексты, используемые в расширении, в DTD и в файлах свойств. Такое разделение позволяет другим разработчикам создавать темы, заменяющие скины, а переводчикам - создавать локализации на разных языках. И всё это - без необходимости изменения кода вашего расширения. Это даёт расширениям Firefox хорошую гибкость.

Файлы Хрома доступны через chrome-протокол. Пример того, как выглядят URI Хрома:

chrome://packagename/section/path/to/file

Так, например, если бы надо было получить доступ к файлу browserOverlay.xul в расширении, Хром-URI был бы:

chrome://xulschoolhello/content/browserOverlay.xul

Если у вас слишком много файлов в Содержании, и вы хотите организовать их в подкаталогах, не нужно ничего менять в chrome.manifest, а нужно, лишь добавить в URI правильный путь после content.

Адресация к файлам Скина и Языка работает точно также, и вам не нужно указывать названий Скина или Языка. Так что, для получения доступа к файлу DTD в расширении "Привет мир", chrome-путь выглядит так: chrome://xulschoolhello/locale/browserOverlay.dtd. Firefox сам знает какой язык нужно искать.

Вот интересный эксперимент.  Откройте новую вкладку Firefox, вбейте в адресной строке: chrome://mozapps/content/downloads/downloads.xul и нажмите клавишу Enter. Удивлены? Вы только что открыли окно загрузок во вкладке Firefox! Вы можете получить доступ к любому файлу Хрома, просто введя его URI в адресной строке. Это может пригодиться, если вы захотите проверить файлы скриптов, являющихся частью Firefox, в своих или других расширениях. Большинство этих файлов открываются как текстовые, за исключением файлов XUL, которые выполняются и отображаются точно так как вы обычно видите их в окне.

Content (Содержание)

В каталоге "content" есть 2 файла. Давайте сначала посмотрим на файл XUL.

XUL файлы - это XML-файлы, определяющие элементы пользовательского интерфейса в Firefox и его расширениях. Создание XUL был вдохновлено языком HTML, так что вы увидите много общего между ними. Однако, XUL по сравнению с HTML улучшен - в нём исправлены ошибки, допущенные в ходе эволюции HTML. XUL позволяет создавать интерфейсы намного богаче и интерактивнее, чем те, что можно создать с помощью HTML. Или, по крайней мере, XUL облегчает работу.

Файлы XUL обычно определяют одно из двух: окна или наложения (оверлейные программы, накладки, слои). В файле downloads.xul, который вы до этого открывали, был код, определявший окно загрузок (Downloads). Файл XUL включён в расширение Hello World в качестве наложения. Наложение расширяет существующие окна, заменяя некоторые их элементы или добавляя новые. Строка, которую мы пропустили в файле chrome.manifest говорится, что этот файл XUL - наложение к главному окну интернет-обозревателя:

overlay chrome://browser/content/browser.xul  chrome://xulschoolhello/content/browserOverlay.xul

С помощью этой строки, Firefox, узнаёт, что ему надо взять содержание browserOverlay.xul и наложить его на главное окно боаузера - browser.xul. Вы можете объявлять наложения для любого окна или диалогового окна в Firefox, но наложение на основное окно браузера - самый распространённый случай на сегодняшний день.

Теперь давайте посмотрим на содержимое нашего файла XUL. Мы пропустим первые несколько строк, потому что они связаны с Темой и Языком, и мы их рассмотрим позже.

<overlay id="xulschoolhello-browser-overlay"
  xmlns="http://www.Mozilla.org/keymaster/gatekeeper/there.is.only.xul">

Ключевой элемент в файле - наложение (оверлей) - overlay. Другие документы XUL используют тег window (окно) или dialog (диалог). У этого элемента есть уникальный идентификатор (id), который вы должны иметь в большинстве элементов в вашем XUL. Второй атрибут - это пространство имён, которое является тем, что вы всегда должны определять в корневом элементе своего XUL. Он говорит, что этот узел и все дочерние узлы являются XUL. Когда вы в одном документе смешиваете разные типы содержания, такие как XUL с HTML или SVG, вам надо только изменить объявления пространства имён.

Вы могли заметить, что мы используем именование в нескольких местах, таких как идентификатор xulschoolhello-browser-overlay. Это стандартные пространства имён, которые мы используем, чтобы избежать конфликтов с Firefox и другими расширениями, а также упростить некоторые задачи разработки. Мы задаём пространство имён для всех идентификаторов и классов стилей в элементах этого наложения, потому что они будут смешаны с другими элементами в главном окне интернет-обозревателя. Если бы мы использовали общие идентификаторы, как container ("контейнер") или input ("ввод"), то они, скорее всего, конфликтовали бы с идентификаторами использующимися в Firefox, или идентификаторами из других наложений расширений. Использование пространства имён позволяет минимизировать проблемы совместимости с другими расширениями. Мы используем ВерблюжийРегистр (CamelCase) для имён файлов, и пишем всё в нижнем регистре с тире для элементов идентификаторов и для имён класса стиля CSS, но вы можете использовать свою собственную систему.
<script type="application/x-javascript"
  src="chrome://xulschoolhello/content/browserOverlay.js" />

Как и в HTML, он включает в себя файл сценария на языке JavaScript. Вы можете вставить столько элементов script (сценарий) в документ XUL, сколько вам нужно. Мы позже рассмотрим его код.

Возможно вы заметили как сформатирован наш код, и удивились правилам, которым мы следуем. Наше главное правило - длина строки не более 80 символов. Это кажется чрезмерно строгим, особенно с XML-файлами, но это число было выбрано, чтобы позволить почти любому текстовому редактору легко обрабатывать эти файлы. Даже старые редакторы для командной строки работают с файлами, в которых строки сокращены до 80 символов. Табуляция проста: 2 пробельных отступа. Мы никогда не используем настоящие символы табуляции, за исключением файлов Makefile, которые будут рассмотрены позже. Большинство наших стандартов кодирования основаны на стандартах Mozilla или других известных и используемых стандартах.

Мы пропустим код, который рассматривается в разделе Языка (локали), перейдя к наиболее важной части содержания:

<menubar id="main-menubar">
  <menu id="xulschoolhello-hello-menu" label="&xulschoolhello.hello.label;"
    accesskey="&xulschoolhello.helloMenu.accesskey;" insertafter="helpMenu">
    <menupopup>
      <menuitem id="xulschoolhello-hello-menu-item"
        label="&xulschoolhello.hello.label;"
        accesskey="&xulschoolhello.helloItem.accesskey;"
        oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" />
    </menupopup>
  </menu>
</menubar>

<vbox id="appmenuSecondaryPane">
  <menu id="xulschoolhello-hello-menu-2" label="&xulschoolhello.hello.label;"
    accesskey="&xulschoolhello.helloMenu.accesskey;"
    insertafter="appmenu_addons">
    <menupopup>
      <menuitem id="xulschoolhello-hello-menu-item-2"
        label="&xulschoolhello.hello.label;"
        accesskey="&xulschoolhello.helloItem.accesskey;"
        oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" />
    </menupopup>
  </menu>
</vbox>

Это код, добавляющий меню "Привет, Мир!" в окно интернет-обозревателя. Тут два почти одинаковых блока кода из-за того, как Firefox сейчас обрабатывает меню. Раньше было так, что на всех платформах была панель с обширным меню. Это изменилось в последней версии Firefox, в частности, в Windows, где видна одна кнопка Firefox, с единым и упрощённым меню опций. Нажатие на кнопку ALT в Windows переключает между кнопкой меню и классическим меню.  Второй блок кода применяется в случае, кнопки меню, а первый блок кода охватывает все остальные случаи. Так как кнопка меню теперь наиболее распространена, мы сосредоточимся на ней.

Для того, чтобы написать этот код, нам нужны некоторые знания кода XUL в файле browser.xul. Нам нужно знать, что идентификатор (id) правой панели в едином меню - это appmenuSecondaryPane.  Мы добавляем собственное меню, и говорим Firefox, добавить его в ту панель, сразу после  пункта "Add-ons" ("Дополнения"). Пример:

insertafter="appmenu_addons"

appmenu_addons -  это идентификатор (id) элемента меню, который соответствует пункту "Дополнения" ("Add-ons") в главном меню. Позже мы увидим, как можно узнать такие штуки, типа идентификаторов элементов браузера, но сейчас давайте посмотрим на те элементы, которые составляют меню "Hello World".

Для классического меню мы добавили меню "Привет мир" прямо в "корень" этого меню, так, чтоб вам было легче его заметить, но так поступать не рекомендуется. Представьте себе, что все расширения станут добавлять пункты меню в главное меню; тогда при установке нескольких расширений этот подход сделает его похожим на приборную панель самолёта, полную ручек и переключателей. В случае единого меню, всё немного сложнее в связи с отсутствием вариантов., Если пункт меню помещается в раздел "Web Developer" ("Веб-разработчик"), то рекомендуется добавить его туда. В противном случае, "Главное меню" может быть единственным выходом.

Одно рекомендуемое место для пунктов меню в классической нише меню - под меню "Инструменты" ("Tools"), так что на самом деле код должен выглядеть так:

<menupopup id="menu_ToolsPopup">
  <menu id="xulschoolhello-hello-menu" label="&xulschoolhello.hello.label;"
    accesskey="&xulschoolhello.helloMenu.accesskey;"
    insertbefore="devToolsEndSeparator">
    <menupopup>
      <menuitem id="xulschoolhello-hello-menu-item"
        label="&xulschoolhello.hello.label;"
        accesskey="&xulschoolhello.helloItem.accesskey;"
        oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);" />
    </menupopup>
  </menu>
</menupopup>

Мы накладываем меню, которое глубже в дереве XUL, но это не важно, потому что всё, что нам нужно - это идентификатор (id) элемента, на который мы хотим наложить свой код. В данном случае это элемент menupopup, находящийся внутри элемента "Инструменты" ("Tools") в menu ("меню"). Атрибут "InsertBefore" диктует Firefox добавить меню в нижнюю часть раздела инструментов разработчика, над его конечным разделителем. Далее в учебнике мы поговорим о меню подробнее.

Теперь давайте посмотрим на действительный код:

oncommand="XULSchoolChrome.BrowserOverlay.sayHello(event);"

Этот атрибут определяет обработчик события. Команда "event" ("событие") - наиболее часто используется в Firefox, так как она соответствует главному действию для большинства элементов пользовательского интерфейса. значение этого атрибута - код на JavaScript, вызывающий функцию. Эта функция определена в JS-файле, включенном ранее тегом "script". JS-функция будет вызвана, когда пользователь нажмёт на пункт меню "Привет Мир" ("Hello World"). Все обработчики событий, назначают специальный объект под названием "event" ("событие"), который обычно передаётся в качестве аргумента функции. Более подробно обработчики событий описаны ниже.

Теперь давайте взглянем на файл JavaScript и посмотрим, что происходит, когда срабатывает событие.

/**
 * XULSchoolChrome namespace.
 */
if ("undefined" == typeof(XULSchoolChrome)) {
  var XULSchoolChrome = {};
};

Определяется пространство имён "XULSchoolChrome". Все объекты и переменные, которые мы определяем в этом JavaScript носят всеобъемлющий характер, это означает, что скрипты в Firefox и других расширениях могут увидеть их и взаимодействовать с ними. Это также значит, что, если мы определим объект под названием "MenuHandler" ("ОбработчикСобытияМеню") или с иным типичным названием, то он, скорее всего, будет конфликтовать с существующим объектом. Так что, нам остаётся здесь сделать - это определить единый всеобъемлющий объект: "XULSchoolChrome". Теперь мы знаем, что все наши объекты находятся внутри этого объекта, который вряд ли будет продублирован или переписан другими расширениями.

Вы можете прочитать больше об операторе "typeof". Если вы не знакомы с JavaScript или с этим синтаксисом, то вам будет интересно узнать, что инициализация объекта сочетанием фигурных скобок "{}" эквивалентна его инициализации строкой "new Object()".

/**
 * Controls the browser overlay for the Hello World extension.
 */
XULSchoolChrome.BrowserOverlay = {

Наконец, BrowserOverlay - это наш объект. Именование и обращение к объектам таким длинным и подробным образом могут показаться поначалу некомфортными, но это оправдано.

Мы используем стиль описания Javadoc во всех пространствах имён, объектах, а также членах объекта. Это такой же стандарт, как используется в коде Mozilla и некоторых инструментах, могущих автоматически порождать документацию из Javadoc.
sayHello : function(aEvent) {
  let stringBundle = document.getElementById("xulschoolhello-string-bundle");
  let message = stringBundle.getString("xulschoolhello.greeting.label");

  window.alert(message);
}

Объявление нашей функции. Три строки кода - это всё, что нужно для её работы. Первая строка в теле функции объявляет переменную "stringBundle", которая будет содержать элемент stringbundle, определённый в наложении. Переменная объявляется с помощью оператора "let" ("пусть"), похожего на var, но с более ограниченной областью. здесь вы можете подробнее прочитать об объявлении let.

Для управления документом XUL, как и в обычном JS, мы можем использовать DOM (Document Object Model). Сначала мы получаем ссылку на элемент stringbundle в документе. Это специальный элемент, позволяющий динамически получать переведённые на нужный язык (локализованные) строки по предоставлении ему лишь "ключа", идентифицирующего текст. Это как-раз то, что мы делаем во второй строке кода. Мы вызываем метод getString элемента связки и получаем переведённое на нужный язык сообщение для показа. Затем мы вызываем функцию "window.alert" с сообщением - так же, как мы могли бы это сделать в HTML-документе.

Локаль

Есть два типа файлов перевода интерфейса (далее - локализации, на правах устоявшегося термина) на нужные языки: DTD и свойства. В этом примере мы используем оба типа. DTD - наиболее эффективный способ показа текста в XUL, поэтому вы должны по возможности использовать именно его. Он весьма негибкий и поэтому он не может быть использован для динамически создаваемого текста, поэтому нужен альтернативный способ получения локализованных строк.

Оглядываясь на код меню, вы, вероятно, заметили, некоторые атрибуты, вроде этих:

label="&xulschoolhello.hello.label;" accesskey="&xulschoolhello.helloItem.accesskey;"

Эти атрибуты определяют текст, который вы видите в меню, и они являются строковыми ключами, определёнными в нашем DTD файле "browserOverlay.dtd". Файл DTD был вовлечён в файле XUL таким кодом:

<!DOCTYPE overlay SYSTEM "chrome://xulschoolhello/locale/browserOverlay.dtd" >

И в файле DTD можно увидеть связь между ключами и локализованными строками:

<!ENTITY xulschoolhello.hello.label            "Hello World!">
<!ENTITY xulschoolhello.helloMenu.accesskey    "l">
<!ENTITY xulschoolhello.helloItem.accesskey    "H">

Обратите внимание, что в файле XUL вы накладываете строковый ключ между амперсандом "&" и точкой с запятой ";", в то время как в файле DTD вы только указываете ключ. Вы можете получить непредсказуемые ошибки синтаксического разбора (парсинга) или неправильную локализацию, если не укажете это правильно.

Клавиши быстрого доступа (также известны как "горячие клавиши". прим. пер.) - это ссылки, позволяющие вам быстро перемещаться по меню, используя только клавиатуру. Они также являются единственным способом навигации по меню для людей с ограниченными возможностями, такими, как частичная или полная слепота, или физическими недостатками, с которыми трудно или невозможно пользоваться мышью. Вы можете легко узнать горячую клавишу быстрого доступа в Windows, так как буква, соответствующая горячей клавише указывается, как на рисунке ниже (буква подчеркнута):

У большинства средств управления пользовательским интерфейсом есть атрибут "accesskey" ("клавиша быстрого доступа"), и его надо использовать. Значение клавиши доступа локализовано - привязано к языковому набору, потому что оно должно соответствовать букве в тексте названия пункта меню. Вам надо также делать всё возможное, чтобы избежать повторения горячей клавиши. Например, они не должны повторяться в пределах меню или подменю. В окне нужно особенно осторожно выбирать клавиши доступа, потому что там обычно ещё больше других средств управления. И особенно внимательно выбирайте клавиши доступа для наложения (Overlay). В нашем случае (в английской версии - прим. пер.) мы не можем использовать английскую букву "H" в качестве горячей клавиши в главном пункте меню, потому что это было бы то же самое как клавиша доступа в Меню "Help" ("помощь"). То же самое с буквой "W" и меню "Window" ("Окно") в Операционной системе "Mac OS". Так что мы остановились на букве "l".

Значения для строк DTD проставляются тогда, когда документ загружается. Если вы запросите значение атрибута "label" у меню "Привет мир!", используя DOM, то вы получите локализованную строку, а не строку ключа. Вы не можете динамически изменять значение атрибута с новым DTD ключом, но можете установить новое значение:

let helloItem = document.getElementById("xulschoolhello-hello-menu-item");

// The alert will say "Hello World!"
alert(helloItem.getAttribute("label"));
// Wrong
helloItem.setAttribute("label", "&xulschoolhello.hello2.label;");
// Better
helloItem.setAttribute("label", "Alternate message");
// Right!
helloItem.setAttribute("label", someStringBundle.getString("xulschoolhello.hello2.label"));

По этой причине строки DTD - не универсальное решение на все случаи локализации, и по этой причине часто нам нужно включать связки строк в файлы XUL:

<stringbundleset id="stringbundleset">
  <stringbundle id="xulschoolhello-string-bundle"
    src="chrome://xulschoolhello/locale/browserOverlay.properties" />
</stringbundleset>

Элемент "stringbundleset" ("строкСвязкаНабор") - это просто вместилище для элементов "stringbundle" (строкСвязка). В документе должна быть только одна причина, по которой мы накладываем "stringbundleset", находящийся в "browser.xul", отсюда очень общий идентификатор ("id"). Мы не включили атрибуты "insertbefore" ("вставитьПеред") или "insertafter" ("вставитьПосле"), потому что порядок следования связок строк не имеет значения. Элемент абсолютно невидим. Если вы не включите ни одного из атрибутов, задающих очерёдность в элементе накладки, то Firefox просто приложит ваш элемент в качестве последнего потомка родительского элемента.

Всё, что нужно для "связки строк" (string bundle) - это идентификатор (чтобы иметь возможность получить элемент позже) и chrome-путь к файлу свойств. И, конечно, нужен сам файл свойств:

xulshoolhello.greeting.label = Hi! How are you?

Пробелы около знака равенства игнорируются. Так же, как в install.rdf, комментарии могут быть добавлены с помощью символа "#" в начале строки с комментарием.  Пустые строки тоже игнорируются.

Вам пригодится уметь включать динамическое содержание как часть локализованных (переведённых на язык пользователя) строк. например, когда вы захотите информировать пользователя о некотором состоянии, связанном с расширением.  Например: "Найдено 5 слов по поисковому запросу". Первой мыслью, вероятно, будет просто объединять строки, и держать отдельно свойство "Найдено" и отдельно свойство "слов по ...".  Это плохая идея.  Это значительно усложняет работу переводчиков ("локализаторов"), кроме того, в разных языках правила грамматики могут полностью менять порядок слов в предложении. Поэтому в свойствах лучше использовать параметры:

xulshoolhello.search.label = Found %S words matching the search query!

Затем используйте "getFormattedString" вместо "getString", чтобы получить локализованную строку. Благодаря этому нам не нужно держать несколько свойств, и это облегчает жизнь переводчикам. Вы можете прочитать больше об этом в разделе "Форматирование текста" в Учебнике XUL ("XUL Tutorial"). Также обратите внимание на статью "Множественное число и локализация", охватывающую функцию "локализации" в Firefox, которая позволит дополнительно уточнить этот последний пример для обработки различных типов формы множественного числа, также зависящих от языков.

Тема (скин)

Отделка (styling. создание дизайна, стилизация) XUL очень похожа на отделку HTML. Мы рассмотрим некоторые различия, когда мы коснёмся коробочной модели XUL-а (XUL Box Model), и других более сложных тем. Есть не так много стилей, которые вы можете сделать для минимального меню и простейшего аварийного предупреждения (alert message), так что расширение "Привет, мир!" только включает пустой файл CSS и обязательный глобальный файл Скина:

<?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
<?xml-stylesheet type="text/css" 
  href="chrome://xulschoolhello/skin/browserOverlay.css"?>

Файл CSS всеобщей темы содержит стили по умолчанию для всех элементов XUL и окон. Когда забывают вовлечь этот файл в окно XUL, то обычно это приводит к интересным и часто к нежелательным результатам. В нашем случае нам действительно не нужно его вовлекать, так как мы накладываем основной файл XUL нашего браузера, а этот файл уже вовлекает в себя эту всеобщую таблицу стилей CSS. Вообще, лучше бы его всегда вовлекать. Так труднее сделать ошибку, не включив его. Если вам интересно, вы можете ввести chrome-путь в адресную строку и посмотреть файл.

Мы коснулись всех файлов в расширении "Привет мир". Теперь вы должны иметь представление об основах участия в разработке расширений, так что теперь нам придется перейти прямо к настройке среды разработки. Но сначала небольшое упражнение.

Упражнение

Измените приветственное сообщение, которое отображается в окне предупреждения, и переместите меню "Привет мир" в меню "Инструменты", которому оно принадлежит. Заново упакуйте XPI и переустановите его. Вы можете просто перетащить файл XPI в браузер, и он будет установлен локально. Проверьте его и убедитесь, что изменения работают. Если у вас возникли проблемы при установке, вполне вероятно, что вы не воспроизвели структуру XPI правильно, возможно, добавив ненужные папки.

Примечание: упаковка расширения действительно состоит только в создании ZIP архива содержимого главного каталога (папки) и последующем изменении расширения файла на ".XPI". Не пакуйте содержащий нужные данные каталог, а строго только его содержимое. Содержимое каталога, файлы chrome.manifest, install.rdf и другие файлы и каталоги должны быть в корневом каталоге архива. Если сжать ещё и содержащий каталог (имеется в виду ещё один уровень вложенности), то ваше расширение не будет загружаться.

Имейте в виду, что в Firefox 4 и выше, в Windows и некоторых дистрибутивах Линукса, меню "Инструменты" по умолчанию скрыто. Оно может быть включено с помощью клавиши <ALT>.

Когда закончите, можете посмотреть по этой ссылке решение: Hello World 2.

Этот учебник сообществу Mozilla был любезно пожертвован фирмой Appcoast.

 

Метки документа и участники

 Внесли вклад в эту страницу: pk.prog, kaifonaft, Jesst, hbvit7
 Обновлялась последний раз: pk.prog,