Основы расширения

by 2 contributors:

Файл 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 говорит Файрфоксу где искать файлы Хрома. Текст расположен вразрядку, чтобы выглядел как таблица, но это не обязательно. Синтаксический анализатор (парсер, parser) игнорирует повторение пробелов.

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

У кожи и языков есть третье значение для указания, какой именно язык или какую именно кожу они расширяют. Может быть несколько кож и языков, касающихся различных скинов и языков. Чаще всего указывают одну запись для кожи - всеобщей кожи - 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/

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

Хром

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

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

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

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

chrome://xulschoolhello/content/browserOverlay.xul

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

Адресация к файлам Кожи и Языка работает точно также, и вам не нужно указывать названий Кожи или Языка. Так что, для получения доступа к файлу DTD в расширении "Привет мир", Хром-путь выглядит так:

Firefox сам знает какой язык нужно искать.

Вот интересный эксперимент.  Откройте новую вкладку Firefox, вбейте в адресной строке:

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

Содержание

В каталоге "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, или идентификаторами из других наложений расширений.  Использование пространства имён позволяет минимизировать проблемы совместимости с другими расширениями. Мы используем ВерблюжийРегистр для имён файлов, и пишем всё в нижнем регистре с тире для элементов идентификаторов и для имён класса стиля 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, в частности, в Окнах, где видна одна кнопка Firefox, с единым и упрощённым меню опций. Нажатие на кнопку ALT в Окнах переключает между кнопкой меню и классическим меню.  Второй блок кода применяется в случае, кнопки меню, а первый блок кода охватывает все остальные случаи. Так как кнопка меню теперь наиболее распространена, мы сосредоточимся на ней.

Для того, чтобы написать этот код, нам нужны некоторые знания кода 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 вы только указываете ключ. Вы можете получить непредсказуемые ошибки синтаксического разбора (парсинга) или неправильную локализацию, если не укажете это правильно.

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

У большинства средств управления пользовательским интерфейсом есть атрибут "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) - это идентификатор (чтобы иметь возможность получить элемент позже) и Хром-путь к файлу свойств. И, конечно, нужен сам файл свойств:

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. Вообще, лучше бы его всегда вовлекать. Так труднее сделать ошибку, не включив его. Если вам интересно, вы можете ввести путь хрома в адресную строку и осмотреть файл.

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

Упражнение

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

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

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

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

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

 

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

Contributors to this page: Jesst, hbvit7
Обновлялась последний раз: Jesst,
Скрыть боковую панель