XUL 覆盖、stringbundleset、getString 不是函数的问题,但 createBundle 方法有效
Trouble with XUL overlay, stringbundleset, getString is not a function, but createBundle method works
所以我正在处理一个旧的 XUL 覆盖附加组件并遇到了这个问题,并将其简化为一个最小的附加组件。想知道如果我做错了什么,如果我误解了什么,或者如何让它按预期工作,是否有人可以向我解释。完整代码如下。在 FF 29.0b1 和 49.0a1 中测试,结果相同。
在主 XUL 文件中,我定义了一个 stringbundleset 和一个 stringbundle,它们都具有(很可能)唯一的 ID。在 JavaScript 文件中,我只想通过元素 ID 获取包(而不是集合),并使用 getString(或 getFormattedString)方法。在主 JavaScript 文件中,我有一个事件侦听器调用一个加载函数,它可以调用其他函数,包括一个 init 函数,我在其中放置了字符串抓取代码。所有字符串变量都使用 var 全局定义(在 init 函数之外)。问题是,我得到 getString is not a function
。此外,console.log()
甚至在函数中的任何地方都不起作用,所以我什至无法检查应该保存返回字符串包的变量的值。
在我的插件中,我在 Options 和 About XUL 文件中使用了完全相同的模式,并且它有效,正如 MDN 文档所说的那样。所以我从示例代码中排除了这个。
如果尝试构建和测试,请注意在示例 JavaScript 代码中,我有尝试使用 XUL stringbundle 并失败的损坏块,以及工作纯 javascript-only使用 createBundle() 的技术被注释掉了。这很容易用 //* code /**/
注释模式修改,只需删除第一个 /
并在另一个块上添加一个 /
并重建 xpi。
这是工作代码应创建的示例屏幕截图。该附加组件依赖于旧的状态栏。我使用了 "The Addon Bar (Restored)" 附加组件。请注意状态栏上的 "TSBS"。右击"TSBS",弹出菜单,顶部为Options
。这些标签是从 .dtd
文件中提取的。 Menu
是一个子菜单,其标签由 tsbs.js
脚本设置,从 .properties
文件中提取值。该示例显示它们是从仅限 JS 的方法中提取的。我正在尝试通过 XUL/DOM 方法让它工作。
我意识到 XUL 附加组件无论如何都会很快消失。我意识到我不应该仅仅依赖状态栏。我意识到我应该只使用 JS-only 方法,因为它看起来更可靠。但我问这个是因为我注意到它并想从中学习。知道如何更正或改进代码模式,或者这是一个已知问题或常见陷阱吗?
Directory tree:
test_string_bundle_set-1.0.0-fx
+-- chrome
| +-- content
| | +-- tsbs.js
| | +-- tsbs.xul
| +-- locale
| | +-- en-US
| | +-- contents.rdf
| | +-- tsbs.dtd
| | +-- tsbs.properties
+-- chrome.manifest
+-- install.rdf
chrome.manifest:
overlay chrome://browser/content/browser.xul chrome://{00735700-7357-7357-7357-073570073570}/content/tsbs.xul
content {00735700-7357-7357-7357-073570073570} chrome/content/
locale {00735700-7357-7357-7357-073570073570} en-US chrome/locale/en-US/
install.rdf:
<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>{00735700-7357-7357-7357-073570073570}</em:id>
<em:version>1.0.0</em:version>
<em:type>2</em:type>
<em:name>Test String Bundle Sets</em:name>
<em:description>Test String Bundle Sets</em:description>
<em:creator>Quite A. Character</em:creator>
<!--Firefox-->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>29.0</em:minVersion>
<em:maxVersion>49.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
chrome/content/tsbs.js:
var tsbs_strings;
var tsbs_string_4;
var tsbs_string_5;
var tsbs_string_6;
function tsbs_load( ) {
tsbs_init( );
return true;
}
function tsbs_close( ) {
return true;
}
window.addEventListener( 'load', tsbs_load, false );
window.addEventListener( 'close', tsbs_close, false );
function tsbs_init( ) {
//* XUL/DOM method
tsbs_strings = document.getElementById( 'tsbs-strings' );
console.log( 'TSBS->tsbs_init()->tsbs_strings: ' + typeof tsbs_strings );
tsbs_string_4 = tsbs_strings.getString( 'tsbs.properties.string.4' );
tsbs_string_5 = tsbs_strings.getString( 'tsbs.properties.string.5' );
tsbs_string_6 = tsbs_strings.getString( 'tsbs.properties.string.6' );
/**/
/* JS-only method
tsbs_strings = Services.strings.createBundle( 'chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.properties' );
console.log( 'TSBS->tsbs_init()->tsbs_strings: ' + typeof tsbs_strings );
tsbs_string_4 = tsbs_strings.GetStringFromName( 'tsbs.properties.string.4' );
tsbs_string_5 = tsbs_strings.GetStringFromName( 'tsbs.properties.string.5' );
tsbs_string_6 = tsbs_strings.GetStringFromName( 'tsbs.properties.string.6' );
/**/
document.getElementById( 'tsbs-item-4' ).label = tsbs_string_4;
document.getElementById( 'tsbs-item-5' ).label = tsbs_string_5;
document.getElementById( 'tsbs-item-6' ).label = tsbs_string_6;
}
chrome/content/tsbs.xul:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.dtd">
<overlay id="tsbs-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://{00735700-7357-7357-7357-073570073570}/content/tsbs.js"/>
<stringbundleset id="tsbs-stringset">
<stringbundle id="tsbs-strings" src="chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.properties"/>
</stringbundleset>
<statusbar id="status-bar">
<statusbarpanel
id="tsbs-display"
label="&tsbs.dtd.statusbarpanel.display;"
pack="end"
context="tsbs-contextmenu"
/>
</statusbar>
<window id="main-window">
<vbox id="tsbs-notifier">
<popupset id="mainPopupSet">
<menupopup id="tsbs-contextmenu" position="before_end">
<menuitem id="tsbs-options" label="&tsbs.dtd.options;"/>
<menuitem label="&tsbs.dtd.string.1;"/>
<menuitem label="&tsbs.dtd.string.2;"/>
<menuitem label="&tsbs.dtd.string.3;"/>
<menu id="tsbs-menu" label="&tsbs.dtd.menu;">
<menupopup id="tsbs-submenu">
<menuitem id="tsbs-item-4"/>
<menuitem id="tsbs-item-5"/>
<menuitem id="tsbs-item-6"/>
</menupopup>
</menu>
</menupopup>
</popupset>
</vbox>
</window>
</overlay>
chrome/locale/en-US/contents.rdf:
<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<Seq about="urn:mozilla:locale:root">
<li resource="urn:mozilla:locale:en-US"/>
</Seq>
<Description about="urn:mozilla:locale:en-US">
<chrome:packages>
<Seq about="urn:mozilla:locale:en-US:packages">
<li resource="urn:mozilla:locale:en-US:{00735700-7357-7357-7357-073570073570}"/>
</Seq>
</chrome:packages>
</Description>
</RDF>
chrome/locale/en-US/tsbs.dtd:
<!ENTITY tsbs.dtd.statusbarpanel.display "TSBS" >
<!ENTITY tsbs.dtd.options "Options" >
<!ENTITY tsbs.dtd.menu "Menu" >
<!ENTITY tsbs.dtd.string.1 "One" >
<!ENTITY tsbs.dtd.string.2 "Two" >
<!ENTITY tsbs.dtd.string.3 "Three" >
chrome/locale/en-US/tsbs.properties:
extensions.{00735700-7357-7357-7357-073570073570}.description=Test String Bundle Sets
tsbs.properties.string.4=four
tsbs.properties.string.5=five
tsbs.properties.string.6=six
我相信这是你的问题:
<stringbundleset id="tsbs-stringset">
在 XUL 覆盖中,如果 <overlay>
的直接子元素具有 ID,则它应该与基本文档中的元素相匹配。 If it does, its contents is inserted under the matching element. If it doesn't this part of an overlay is ignored.
browser.xul can be matched using 中现有的 stringbundleset:
<stringbundleset id="stringbundleset">
另外,我不认为有 'close' 事件(使用 'unload'),并且自 Firefox 2 左右以来您不需要 contents.rdf。关于 console.log()
不工作 - 你检查了 Browser Console,而不是 Web 控制台,对吧?
所以我正在处理一个旧的 XUL 覆盖附加组件并遇到了这个问题,并将其简化为一个最小的附加组件。想知道如果我做错了什么,如果我误解了什么,或者如何让它按预期工作,是否有人可以向我解释。完整代码如下。在 FF 29.0b1 和 49.0a1 中测试,结果相同。
在主 XUL 文件中,我定义了一个 stringbundleset 和一个 stringbundle,它们都具有(很可能)唯一的 ID。在 JavaScript 文件中,我只想通过元素 ID 获取包(而不是集合),并使用 getString(或 getFormattedString)方法。在主 JavaScript 文件中,我有一个事件侦听器调用一个加载函数,它可以调用其他函数,包括一个 init 函数,我在其中放置了字符串抓取代码。所有字符串变量都使用 var 全局定义(在 init 函数之外)。问题是,我得到 getString is not a function
。此外,console.log()
甚至在函数中的任何地方都不起作用,所以我什至无法检查应该保存返回字符串包的变量的值。
在我的插件中,我在 Options 和 About XUL 文件中使用了完全相同的模式,并且它有效,正如 MDN 文档所说的那样。所以我从示例代码中排除了这个。
如果尝试构建和测试,请注意在示例 JavaScript 代码中,我有尝试使用 XUL stringbundle 并失败的损坏块,以及工作纯 javascript-only使用 createBundle() 的技术被注释掉了。这很容易用 //* code /**/
注释模式修改,只需删除第一个 /
并在另一个块上添加一个 /
并重建 xpi。
这是工作代码应创建的示例屏幕截图。该附加组件依赖于旧的状态栏。我使用了 "The Addon Bar (Restored)" 附加组件。请注意状态栏上的 "TSBS"。右击"TSBS",弹出菜单,顶部为Options
。这些标签是从 .dtd
文件中提取的。 Menu
是一个子菜单,其标签由 tsbs.js
脚本设置,从 .properties
文件中提取值。该示例显示它们是从仅限 JS 的方法中提取的。我正在尝试通过 XUL/DOM 方法让它工作。
我意识到 XUL 附加组件无论如何都会很快消失。我意识到我不应该仅仅依赖状态栏。我意识到我应该只使用 JS-only 方法,因为它看起来更可靠。但我问这个是因为我注意到它并想从中学习。知道如何更正或改进代码模式,或者这是一个已知问题或常见陷阱吗?
Directory tree:
test_string_bundle_set-1.0.0-fx
+-- chrome
| +-- content
| | +-- tsbs.js
| | +-- tsbs.xul
| +-- locale
| | +-- en-US
| | +-- contents.rdf
| | +-- tsbs.dtd
| | +-- tsbs.properties
+-- chrome.manifest
+-- install.rdf
chrome.manifest:
overlay chrome://browser/content/browser.xul chrome://{00735700-7357-7357-7357-073570073570}/content/tsbs.xul
content {00735700-7357-7357-7357-073570073570} chrome/content/
locale {00735700-7357-7357-7357-073570073570} en-US chrome/locale/en-US/
install.rdf:
<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>{00735700-7357-7357-7357-073570073570}</em:id>
<em:version>1.0.0</em:version>
<em:type>2</em:type>
<em:name>Test String Bundle Sets</em:name>
<em:description>Test String Bundle Sets</em:description>
<em:creator>Quite A. Character</em:creator>
<!--Firefox-->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>29.0</em:minVersion>
<em:maxVersion>49.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>
chrome/content/tsbs.js:
var tsbs_strings;
var tsbs_string_4;
var tsbs_string_5;
var tsbs_string_6;
function tsbs_load( ) {
tsbs_init( );
return true;
}
function tsbs_close( ) {
return true;
}
window.addEventListener( 'load', tsbs_load, false );
window.addEventListener( 'close', tsbs_close, false );
function tsbs_init( ) {
//* XUL/DOM method
tsbs_strings = document.getElementById( 'tsbs-strings' );
console.log( 'TSBS->tsbs_init()->tsbs_strings: ' + typeof tsbs_strings );
tsbs_string_4 = tsbs_strings.getString( 'tsbs.properties.string.4' );
tsbs_string_5 = tsbs_strings.getString( 'tsbs.properties.string.5' );
tsbs_string_6 = tsbs_strings.getString( 'tsbs.properties.string.6' );
/**/
/* JS-only method
tsbs_strings = Services.strings.createBundle( 'chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.properties' );
console.log( 'TSBS->tsbs_init()->tsbs_strings: ' + typeof tsbs_strings );
tsbs_string_4 = tsbs_strings.GetStringFromName( 'tsbs.properties.string.4' );
tsbs_string_5 = tsbs_strings.GetStringFromName( 'tsbs.properties.string.5' );
tsbs_string_6 = tsbs_strings.GetStringFromName( 'tsbs.properties.string.6' );
/**/
document.getElementById( 'tsbs-item-4' ).label = tsbs_string_4;
document.getElementById( 'tsbs-item-5' ).label = tsbs_string_5;
document.getElementById( 'tsbs-item-6' ).label = tsbs_string_6;
}
chrome/content/tsbs.xul:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.dtd">
<overlay id="tsbs-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://{00735700-7357-7357-7357-073570073570}/content/tsbs.js"/>
<stringbundleset id="tsbs-stringset">
<stringbundle id="tsbs-strings" src="chrome://{00735700-7357-7357-7357-073570073570}/locale/tsbs.properties"/>
</stringbundleset>
<statusbar id="status-bar">
<statusbarpanel
id="tsbs-display"
label="&tsbs.dtd.statusbarpanel.display;"
pack="end"
context="tsbs-contextmenu"
/>
</statusbar>
<window id="main-window">
<vbox id="tsbs-notifier">
<popupset id="mainPopupSet">
<menupopup id="tsbs-contextmenu" position="before_end">
<menuitem id="tsbs-options" label="&tsbs.dtd.options;"/>
<menuitem label="&tsbs.dtd.string.1;"/>
<menuitem label="&tsbs.dtd.string.2;"/>
<menuitem label="&tsbs.dtd.string.3;"/>
<menu id="tsbs-menu" label="&tsbs.dtd.menu;">
<menupopup id="tsbs-submenu">
<menuitem id="tsbs-item-4"/>
<menuitem id="tsbs-item-5"/>
<menuitem id="tsbs-item-6"/>
</menupopup>
</menu>
</menupopup>
</popupset>
</vbox>
</window>
</overlay>
chrome/locale/en-US/contents.rdf:
<?xml version="1.0" encoding="UTF-8"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<Seq about="urn:mozilla:locale:root">
<li resource="urn:mozilla:locale:en-US"/>
</Seq>
<Description about="urn:mozilla:locale:en-US">
<chrome:packages>
<Seq about="urn:mozilla:locale:en-US:packages">
<li resource="urn:mozilla:locale:en-US:{00735700-7357-7357-7357-073570073570}"/>
</Seq>
</chrome:packages>
</Description>
</RDF>
chrome/locale/en-US/tsbs.dtd:
<!ENTITY tsbs.dtd.statusbarpanel.display "TSBS" >
<!ENTITY tsbs.dtd.options "Options" >
<!ENTITY tsbs.dtd.menu "Menu" >
<!ENTITY tsbs.dtd.string.1 "One" >
<!ENTITY tsbs.dtd.string.2 "Two" >
<!ENTITY tsbs.dtd.string.3 "Three" >
chrome/locale/en-US/tsbs.properties:
extensions.{00735700-7357-7357-7357-073570073570}.description=Test String Bundle Sets
tsbs.properties.string.4=four
tsbs.properties.string.5=five
tsbs.properties.string.6=six
我相信这是你的问题:
<stringbundleset id="tsbs-stringset">
在 XUL 覆盖中,如果 <overlay>
的直接子元素具有 ID,则它应该与基本文档中的元素相匹配。 If it does, its contents is inserted under the matching element. If it doesn't this part of an overlay is ignored.
browser.xul can be matched using 中现有的 stringbundleset:
<stringbundleset id="stringbundleset">
另外,我不认为有 'close' 事件(使用 'unload'),并且自 Firefox 2 左右以来您不需要 contents.rdf。关于 console.log()
不工作 - 你检查了 Browser Console,而不是 Web 控制台,对吧?