update: dtd2ftl
This commit is contained in:
		
							parent
							
								
									8540d1b4cf
								
							
						
					
					
						commit
						25081bf450
					
				@ -28,7 +28,7 @@ This is a plugin template for [Zotero](https://www.zotero.org/). Plugins using t
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
📌[Zotero Plugin Template](https://github.com/windingwind/zotero-plugin-template)(This repo)
 | 
					📌[Zotero Plugin Template](https://github.com/windingwind/zotero-plugin-template)(This repo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> 👍You are currently in `bootstrap` extension mode. To use `overlay` mode, plsase switch to `overlay` branch in git.
 | 
					> 👍You are currently in `bootstrap` extension mode. To use `overlay` mode, please switch to `overlay` branch in git.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
> 👁 Watch this repo so that you can be notified whenever there are fixes & updates.
 | 
					> 👁 Watch this repo so that you can be notified whenever there are fixes & updates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -40,6 +40,8 @@ If you are using this repo, I recommended that you put this badge ([![Using Zote
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Features
 | 
					## Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> ❗The localization system is upgraded (dtd is deprecated and we do not use .properties anymore). Only supports Zotero 7.0.0-beta.12 or higher now. If you want to support Zotero 6, you may need to use `dtd`, `properties`, and `ftl` at the same time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Event-driven, functional programming, under extensive skeleton;
 | 
					- Event-driven, functional programming, under extensive skeleton;
 | 
				
			||||||
- Simple and user-friendly, works out-of-the-box.
 | 
					- Simple and user-friendly, works out-of-the-box.
 | 
				
			||||||
- ⭐[New!]Auto hot reload! Whenever the source code is modified, automatically compile and reload. [See here→](#auto-hot-reload)
 | 
					- ⭐[New!]Auto hot reload! Whenever the source code is modified, automatically compile and reload. [See here→](#auto-hot-reload)
 | 
				
			||||||
@ -221,7 +223,6 @@ Tired of endless restarting? Forget about it!
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
When file changes are detected in `src` or `addon`, the plugin will be automatically compiled and reloaded.
 | 
					When file changes are detected in `src` or `addon`, the plugin will be automatically compiled and reloaded.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
<details style="text-indent: 2em">
 | 
					<details style="text-indent: 2em">
 | 
				
			||||||
<summary>💡 Steps to add this feature to an existing plugin</summary>
 | 
					<summary>💡 Steps to add this feature to an existing plugin</summary>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -232,8 +233,6 @@ When file changes are detected in `src` or `addon`, the plugin will be automatic
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
</details>
 | 
					</details>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Debug in Zotero
 | 
					### Debug in Zotero
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can also:
 | 
					You can also:
 | 
				
			||||||
 | 
				
			|||||||
@ -1,18 +1,22 @@
 | 
				
			|||||||
 | 
					<linkset>
 | 
				
			||||||
 | 
					  <html:link rel="localization" href="__addonRef__-preferences.ftl" />
 | 
				
			||||||
 | 
					</linkset>
 | 
				
			||||||
<vbox
 | 
					<vbox
 | 
				
			||||||
  id="zotero-prefpane-__addonRef__"
 | 
					  id="zotero-prefpane-__addonRef__"
 | 
				
			||||||
  onload="Zotero.__addonInstance__.hooks.onPrefsEvent('load', {window})"
 | 
					  onload="Zotero.__addonInstance__.hooks.onPrefsEvent('load', {window})"
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
  <groupbox>
 | 
					  <groupbox>
 | 
				
			||||||
    <label><html:h2>&zotero.__addonRef__.pref.title;</html:h2></label>
 | 
					    <label><html:h2 data-l10n-id="pref-title"></html:h2></label>
 | 
				
			||||||
    <checkbox
 | 
					    <checkbox
 | 
				
			||||||
      id="zotero-prefpane-__addonRef__-enable"
 | 
					      id="zotero-prefpane-__addonRef__-enable"
 | 
				
			||||||
      label="&zotero.__addonRef__.pref.enable.label;"
 | 
					 | 
				
			||||||
      preference="extensions.zotero.__addonRef__.enable"
 | 
					      preference="extensions.zotero.__addonRef__.enable"
 | 
				
			||||||
 | 
					      data-l10n-id="pref-enable"
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
    <hbox>
 | 
					    <hbox>
 | 
				
			||||||
      <html:label for="zotero-prefpane-__addonRef__-input"
 | 
					      <html:label
 | 
				
			||||||
        >&zotero.__addonRef__.pref.input.label;</html:label
 | 
					        for="zotero-prefpane-__addonRef__-input"
 | 
				
			||||||
      >
 | 
					        data-l10n-id="pref-input"
 | 
				
			||||||
 | 
					      ></html:label>
 | 
				
			||||||
      <html:input
 | 
					      <html:input
 | 
				
			||||||
        type="text"
 | 
					        type="text"
 | 
				
			||||||
        id="zotero-prefpane-__addonRef__-input"
 | 
					        id="zotero-prefpane-__addonRef__-input"
 | 
				
			||||||
@ -25,7 +29,8 @@
 | 
				
			|||||||
  </groupbox>
 | 
					  </groupbox>
 | 
				
			||||||
</vbox>
 | 
					</vbox>
 | 
				
			||||||
<vbox>
 | 
					<vbox>
 | 
				
			||||||
  <label
 | 
					  <html:label
 | 
				
			||||||
    value="&zotero.__addonRef__.help.version.label;  &zotero.__addonRef__.help.releasetime.label;"
 | 
					    data-l10n-id="pref-help"
 | 
				
			||||||
  ></label>
 | 
					    data-l10n-args='{"time": "__buildTime__","name": "__addonName__","version":"__buildVersion__"}'
 | 
				
			||||||
 | 
					  ></html:label>
 | 
				
			||||||
</vbox>
 | 
					</vbox>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +0,0 @@
 | 
				
			|||||||
startup.begin=Addon is loading
 | 
					 | 
				
			||||||
startup.finish=Addon is ready
 | 
					 | 
				
			||||||
menuitem.label=Addon Template: Helper Examples
 | 
					 | 
				
			||||||
menupopup.label=Addon Template: Menupopup
 | 
					 | 
				
			||||||
menuitem.submenulabel=Addon Template
 | 
					 | 
				
			||||||
menuitem.filemenulabel=Addon Template: File Menuitem
 | 
					 | 
				
			||||||
prefs.title=Template
 | 
					 | 
				
			||||||
prefs.table.title=Title
 | 
					 | 
				
			||||||
prefs.table.detail=Detail
 | 
					 | 
				
			||||||
tabpanel.lib.tab.label=Lib Tab
 | 
					 | 
				
			||||||
tabpanel.reader.tab.label=Reader Tab
 | 
					 | 
				
			||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
<!ENTITY zotero.__addonRef__.pref.title "Addon Template Example">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.itemmenu.test.label "addon template">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.pref.enable.label "Enable">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.pref.input.label "Input">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.help.version.label "__addonName__ VERSION __buildVersion__">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.help.releasetime.label "Build __buildTime__">
 | 
					 | 
				
			||||||
@ -1,11 +0,0 @@
 | 
				
			|||||||
startup.begin=插件加载中
 | 
					 | 
				
			||||||
startup.finish=插件已就绪
 | 
					 | 
				
			||||||
menuitem.label=插件模板: 帮助工具样例
 | 
					 | 
				
			||||||
menupopup.label=插件模板: 弹出菜单
 | 
					 | 
				
			||||||
menuitem.submenulabel=插件模板:子菜单
 | 
					 | 
				
			||||||
menuitem.filemenulabel=插件模板: 文件菜单
 | 
					 | 
				
			||||||
prefs.title=插件模板
 | 
					 | 
				
			||||||
prefs.table.title=标题
 | 
					 | 
				
			||||||
prefs.table.detail=详情
 | 
					 | 
				
			||||||
tabpanel.lib.tab.label=库标签
 | 
					 | 
				
			||||||
tabpanel.reader.tab.label=阅读器标签
 | 
					 | 
				
			||||||
@ -1,7 +0,0 @@
 | 
				
			|||||||
<!ENTITY zotero.__addonRef__.pref.title "插件模板设置示例">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.itemmenu.test.label "插件模板">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.pref.enable.label "开启">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.pref.input.label "输入">
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.help.version.label "__addonName__ 版本 __buildVersion__">
 | 
					 | 
				
			||||||
<!ENTITY zotero.__addonRef__.help.releasetime.label "Build __buildTime__">
 | 
					 | 
				
			||||||
							
								
								
									
										11
									
								
								addon/locale/en-US/addon.ftl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								addon/locale/en-US/addon.ftl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					startup-begin = Addon is loading
 | 
				
			||||||
 | 
					startup-finish = Addon is ready
 | 
				
			||||||
 | 
					menuitem-label = Addon Template: Helper Examples
 | 
				
			||||||
 | 
					menupopup-label = Addon Template: Menupopup
 | 
				
			||||||
 | 
					menuitem-submenulabel = Addon Template
 | 
				
			||||||
 | 
					menuitem-filemenulabel = Addon Template: File Menuitem
 | 
				
			||||||
 | 
					prefs-title = Template
 | 
				
			||||||
 | 
					prefs-table-title = Title
 | 
				
			||||||
 | 
					prefs-table-detail = Detail
 | 
				
			||||||
 | 
					tabpanel-lib-tab-label = Lib Tab
 | 
				
			||||||
 | 
					tabpanel-reader-tab-label = Reader Tab
 | 
				
			||||||
							
								
								
									
										4
									
								
								addon/locale/en-US/preferences.ftl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								addon/locale/en-US/preferences.ftl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					pref-title = Addon Template Example
 | 
				
			||||||
 | 
					pref-enable =
 | 
				
			||||||
 | 
					    .label = Enable
 | 
				
			||||||
 | 
					pref-help = { $name } Build { $version } { $time }
 | 
				
			||||||
							
								
								
									
										11
									
								
								addon/locale/zh-CN/addon.ftl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								addon/locale/zh-CN/addon.ftl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					startup-begin = 插件加载中
 | 
				
			||||||
 | 
					startup-finish = 插件已就绪
 | 
				
			||||||
 | 
					menuitem-label = 插件模板: 帮助工具样例
 | 
				
			||||||
 | 
					menupopup-label = 插件模板: 弹出菜单
 | 
				
			||||||
 | 
					menuitem-submenulabel = 插件模板:子菜单
 | 
				
			||||||
 | 
					menuitem-filemenulabel = 插件模板: 文件菜单
 | 
				
			||||||
 | 
					prefs-title = 插件模板
 | 
				
			||||||
 | 
					prefs-table-title = 标题
 | 
				
			||||||
 | 
					prefs-table-detail = 详情
 | 
				
			||||||
 | 
					tabpanel-lib-tab-label = 库标签
 | 
				
			||||||
 | 
					tabpanel-reader-tab-label = 阅读器标签
 | 
				
			||||||
							
								
								
									
										5
									
								
								addon/locale/zh-CN/preferences.ftl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								addon/locale/zh-CN/preferences.ftl
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					pref-title = 插件模板设置示例
 | 
				
			||||||
 | 
					pref-enable =
 | 
				
			||||||
 | 
					    .label = 开启
 | 
				
			||||||
 | 
					pref-input = 输入
 | 
				
			||||||
 | 
					pref-help = { $name } Build { $version } { $time }
 | 
				
			||||||
@ -9,6 +9,7 @@ import {
 | 
				
			|||||||
  mkdirSync,
 | 
					  mkdirSync,
 | 
				
			||||||
  readdirSync,
 | 
					  readdirSync,
 | 
				
			||||||
  rmSync,
 | 
					  rmSync,
 | 
				
			||||||
 | 
					  renameSync,
 | 
				
			||||||
} from "fs";
 | 
					} from "fs";
 | 
				
			||||||
import { env, exit } from "process";
 | 
					import { env, exit } from "process";
 | 
				
			||||||
import replaceInFile from "replace-in-file";
 | 
					import replaceInFile from "replace-in-file";
 | 
				
			||||||
@ -158,6 +159,30 @@ async function main() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  console.log("[Build] Replace OK");
 | 
					  console.log("[Build] Replace OK");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Walk the builds/addon/locale folder's sub folders and rename *.ftl to addonRef-*.ftl
 | 
				
			||||||
 | 
					  const localeDir = join(buildDir, "addon/locale");
 | 
				
			||||||
 | 
					  const localeFolders = readdirSync(localeDir, { withFileTypes: true })
 | 
				
			||||||
 | 
					    .filter((dirent) => dirent.isDirectory())
 | 
				
			||||||
 | 
					    .map((dirent) => dirent.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const localeSubFolder of localeFolders) {
 | 
				
			||||||
 | 
					    const localeSubDir = join(localeDir, localeSubFolder);
 | 
				
			||||||
 | 
					    const localeSubFiles = readdirSync(localeSubDir, {
 | 
				
			||||||
 | 
					      withFileTypes: true,
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					      .filter((dirent) => dirent.isFile())
 | 
				
			||||||
 | 
					      .map((dirent) => dirent.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const localeSubFile of localeSubFiles) {
 | 
				
			||||||
 | 
					      if (localeSubFile.endsWith(".ftl")) {
 | 
				
			||||||
 | 
					        renameSync(
 | 
				
			||||||
 | 
					          join(localeSubDir, localeSubFile),
 | 
				
			||||||
 | 
					          join(localeSubDir, `${config.addonRef}-${localeSubFile}`)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  console.log("[Build] Addon prepare OK");
 | 
					  console.log("[Build] Addon prepare OK");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  await zip.compressDir(
 | 
					  await zip.compressDir(
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ import {
 | 
				
			|||||||
  UIExampleFactory,
 | 
					  UIExampleFactory,
 | 
				
			||||||
} from "./modules/examples";
 | 
					} from "./modules/examples";
 | 
				
			||||||
import { config } from "../package.json";
 | 
					import { config } from "../package.json";
 | 
				
			||||||
import { getString, initLocale } from "./utils/locale";
 | 
					import { getStringAsync, initLocale } from "./utils/locale";
 | 
				
			||||||
import { registerPrefsScripts } from "./modules/preferenceScript";
 | 
					import { registerPrefsScripts } from "./modules/preferenceScript";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function onStartup() {
 | 
					async function onStartup() {
 | 
				
			||||||
@ -26,7 +26,7 @@ async function onStartup() {
 | 
				
			|||||||
    closeTime: -1,
 | 
					    closeTime: -1,
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
    .createLine({
 | 
					    .createLine({
 | 
				
			||||||
      text: getString("startup.begin"),
 | 
					      text: await getStringAsync("startup-begin"),
 | 
				
			||||||
      type: "default",
 | 
					      type: "default",
 | 
				
			||||||
      progress: 0,
 | 
					      progress: 0,
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
@ -41,7 +41,7 @@ async function onStartup() {
 | 
				
			|||||||
  await Zotero.Promise.delay(1000);
 | 
					  await Zotero.Promise.delay(1000);
 | 
				
			||||||
  popupWin.changeLine({
 | 
					  popupWin.changeLine({
 | 
				
			||||||
    progress: 30,
 | 
					    progress: 30,
 | 
				
			||||||
    text: `[30%] ${getString("startup.begin")}`,
 | 
					    text: `[30%] ${await getStringAsync("startup-begin")}`,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  UIExampleFactory.registerStyleSheet();
 | 
					  UIExampleFactory.registerStyleSheet();
 | 
				
			||||||
@ -74,7 +74,7 @@ async function onStartup() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  popupWin.changeLine({
 | 
					  popupWin.changeLine({
 | 
				
			||||||
    progress: 100,
 | 
					    progress: 100,
 | 
				
			||||||
    text: `[100%] ${getString("startup.finish")}`,
 | 
					    text: `[100%] ${await getStringAsync("startup-finish")}`,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  popupWin.startCloseTimer(5000);
 | 
					  popupWin.startCloseTimer(5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { config } from "../../package.json";
 | 
					import { config } from "../../package.json";
 | 
				
			||||||
import { getString } from "../utils/locale";
 | 
					import { getStringAsync } from "../utils/locale";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function example(
 | 
					function example(
 | 
				
			||||||
  target: any,
 | 
					  target: any,
 | 
				
			||||||
@ -71,13 +71,12 @@ export class BasicExampleFactory {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @example
 | 
					  @example
 | 
				
			||||||
  static registerPrefs() {
 | 
					  static async registerPrefs() {
 | 
				
			||||||
    const prefOptions = {
 | 
					    const prefOptions = {
 | 
				
			||||||
      pluginID: config.addonID,
 | 
					      pluginID: config.addonID,
 | 
				
			||||||
      src: rootURI + "chrome/content/preferences.xhtml",
 | 
					      src: rootURI + "chrome/content/preferences.xhtml",
 | 
				
			||||||
      label: getString("prefs.title"),
 | 
					      label: await getStringAsync("prefs-title"),
 | 
				
			||||||
      image: `chrome://${config.addonRef}/content/icons/favicon.png`,
 | 
					      image: `chrome://${config.addonRef}/content/icons/favicon.png`,
 | 
				
			||||||
      extraDTD: [`chrome://${config.addonRef}/locale/overlay.dtd`],
 | 
					 | 
				
			||||||
      defaultXUL: true,
 | 
					      defaultXUL: true,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    ztoolkit.PreferencePane.register(prefOptions);
 | 
					    ztoolkit.PreferencePane.register(prefOptions);
 | 
				
			||||||
@ -198,29 +197,29 @@ export class UIExampleFactory {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @example
 | 
					  @example
 | 
				
			||||||
  static registerRightClickMenuItem() {
 | 
					  static async registerRightClickMenuItem() {
 | 
				
			||||||
    const menuIcon = `chrome://${config.addonRef}/content/icons/favicon@0.5x.png`;
 | 
					    const menuIcon = `chrome://${config.addonRef}/content/icons/favicon@0.5x.png`;
 | 
				
			||||||
    // item menuitem with icon
 | 
					    // item menuitem with icon
 | 
				
			||||||
    ztoolkit.Menu.register("item", {
 | 
					    ztoolkit.Menu.register("item", {
 | 
				
			||||||
      tag: "menuitem",
 | 
					      tag: "menuitem",
 | 
				
			||||||
      id: "zotero-itemmenu-addontemplate-test",
 | 
					      id: "zotero-itemmenu-addontemplate-test",
 | 
				
			||||||
      label: getString("menuitem.label"),
 | 
					      label: await getStringAsync("menuitem-label"),
 | 
				
			||||||
      commandListener: (ev) => addon.hooks.onDialogEvents("dialogExample"),
 | 
					      commandListener: (ev) => addon.hooks.onDialogEvents("dialogExample"),
 | 
				
			||||||
      icon: menuIcon,
 | 
					      icon: menuIcon,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @example
 | 
					  @example
 | 
				
			||||||
  static registerRightClickMenuPopup() {
 | 
					  static async registerRightClickMenuPopup() {
 | 
				
			||||||
    ztoolkit.Menu.register(
 | 
					    ztoolkit.Menu.register(
 | 
				
			||||||
      "item",
 | 
					      "item",
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        tag: "menu",
 | 
					        tag: "menu",
 | 
				
			||||||
        label: getString("menupopup.label"),
 | 
					        label: await getStringAsync("menupopup-label"),
 | 
				
			||||||
        children: [
 | 
					        children: [
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
            tag: "menuitem",
 | 
					            tag: "menuitem",
 | 
				
			||||||
            label: getString("menuitem.submenulabel"),
 | 
					            label: await getStringAsync("menuitem-submenulabel"),
 | 
				
			||||||
            oncommand: "alert('Hello World! Sub Menuitem.')",
 | 
					            oncommand: "alert('Hello World! Sub Menuitem.')",
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
@ -233,14 +232,14 @@ export class UIExampleFactory {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @example
 | 
					  @example
 | 
				
			||||||
  static registerWindowMenuWithSeparator() {
 | 
					  static async registerWindowMenuWithSeparator() {
 | 
				
			||||||
    ztoolkit.Menu.register("menuFile", {
 | 
					    ztoolkit.Menu.register("menuFile", {
 | 
				
			||||||
      tag: "menuseparator",
 | 
					      tag: "menuseparator",
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    // menu->File menuitem
 | 
					    // menu->File menuitem
 | 
				
			||||||
    ztoolkit.Menu.register("menuFile", {
 | 
					    ztoolkit.Menu.register("menuFile", {
 | 
				
			||||||
      tag: "menuitem",
 | 
					      tag: "menuitem",
 | 
				
			||||||
      label: getString("menuitem.filemenulabel"),
 | 
					      label: await getStringAsync("menuitem-filemenulabel"),
 | 
				
			||||||
      oncommand: "alert('Hello World! File Menuitem.')",
 | 
					      oncommand: "alert('Hello World! File Menuitem.')",
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -346,9 +345,9 @@ export class UIExampleFactory {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @example
 | 
					  @example
 | 
				
			||||||
  static registerLibraryTabPanel() {
 | 
					  static async registerLibraryTabPanel() {
 | 
				
			||||||
    const tabId = ztoolkit.LibraryTabPanel.register(
 | 
					    const tabId = ztoolkit.LibraryTabPanel.register(
 | 
				
			||||||
      getString("tabpanel.lib.tab.label"),
 | 
					      await getStringAsync("tabpanel-lib-tab-label"),
 | 
				
			||||||
      (panel: XUL.Element, win: Window) => {
 | 
					      (panel: XUL.Element, win: Window) => {
 | 
				
			||||||
        const elem = ztoolkit.UI.createElement(win.document, "vbox", {
 | 
					        const elem = ztoolkit.UI.createElement(win.document, "vbox", {
 | 
				
			||||||
          children: [
 | 
					          children: [
 | 
				
			||||||
@ -392,7 +391,7 @@ export class UIExampleFactory {
 | 
				
			|||||||
  @example
 | 
					  @example
 | 
				
			||||||
  static async registerReaderTabPanel() {
 | 
					  static async registerReaderTabPanel() {
 | 
				
			||||||
    const tabId = await ztoolkit.ReaderTabPanel.register(
 | 
					    const tabId = await ztoolkit.ReaderTabPanel.register(
 | 
				
			||||||
      getString("tabpanel.reader.tab.label"),
 | 
					      await getStringAsync("tabpanel-reader-tab-label"),
 | 
				
			||||||
      (
 | 
					      (
 | 
				
			||||||
        panel: XUL.TabPanel | undefined,
 | 
					        panel: XUL.TabPanel | undefined,
 | 
				
			||||||
        deck: XUL.Deck,
 | 
					        deck: XUL.Deck,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { config } from "../../package.json";
 | 
					import { config } from "../../package.json";
 | 
				
			||||||
import { getString } from "../utils/locale";
 | 
					import { getStringAsync } from "../utils/locale";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function registerPrefsScripts(_window: Window) {
 | 
					export async function registerPrefsScripts(_window: Window) {
 | 
				
			||||||
  // This function is called when the prefs window is opened
 | 
					  // This function is called when the prefs window is opened
 | 
				
			||||||
  // See addon/chrome/content/preferences.xul onpaneload
 | 
					  // See addon/chrome/content/preferences.xul onpaneload
 | 
				
			||||||
  if (!addon.data.prefs) {
 | 
					  if (!addon.data.prefs) {
 | 
				
			||||||
@ -10,13 +10,13 @@ export function registerPrefsScripts(_window: Window) {
 | 
				
			|||||||
      columns: [
 | 
					      columns: [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          dataKey: "title",
 | 
					          dataKey: "title",
 | 
				
			||||||
          label: "prefs.table.title",
 | 
					          label: await getStringAsync("prefs-table-title"),
 | 
				
			||||||
          fixedWidth: true,
 | 
					          fixedWidth: true,
 | 
				
			||||||
          width: 100,
 | 
					          width: 100,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          dataKey: "detail",
 | 
					          dataKey: "detail",
 | 
				
			||||||
          label: "prefs.table.detail",
 | 
					          label: await getStringAsync("prefs-table-detail"),
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      rows: [
 | 
					      rows: [
 | 
				
			||||||
@ -53,11 +53,7 @@ async function updatePrefsUI() {
 | 
				
			|||||||
      id: `${config.addonRef}-prefs-table`,
 | 
					      id: `${config.addonRef}-prefs-table`,
 | 
				
			||||||
      // Do not use setLocale, as it modifies the Zotero.Intl.strings
 | 
					      // Do not use setLocale, as it modifies the Zotero.Intl.strings
 | 
				
			||||||
      // Set locales directly to columns
 | 
					      // Set locales directly to columns
 | 
				
			||||||
      columns: addon.data.prefs?.columns.map((column) =>
 | 
					      columns: addon.data.prefs?.columns,
 | 
				
			||||||
        Object.assign(column, {
 | 
					 | 
				
			||||||
          label: getString(column.label) || column.label,
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      showHeader: true,
 | 
					      showHeader: true,
 | 
				
			||||||
      multiSelect: true,
 | 
					      multiSelect: true,
 | 
				
			||||||
      staticColumns: true,
 | 
					      staticColumns: true,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,29 +1,52 @@
 | 
				
			|||||||
import { config } from "../../package.json";
 | 
					import { config } from "../../package.json";
 | 
				
			||||||
 | 
					import { waitUntil } from "./wait";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Initialize locale data
 | 
					 * Initialize locale data
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function initLocale() {
 | 
					export function initLocale() {
 | 
				
			||||||
  addon.data.locale = {
 | 
					  ztoolkit.UI.appendElement(
 | 
				
			||||||
    stringBundle: Components.classes["@mozilla.org/intl/stringbundle;1"]
 | 
					    {
 | 
				
			||||||
      .getService(Components.interfaces.nsIStringBundleService)
 | 
					      tag: "link",
 | 
				
			||||||
      .createBundle(`chrome://${config.addonRef}/locale/addon.properties`),
 | 
					      namespace: "html",
 | 
				
			||||||
  };
 | 
					      properties: {
 | 
				
			||||||
 | 
					        rel: "localization",
 | 
				
			||||||
 | 
					        href: `${config.addonRef}-addon.ftl`,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    document.querySelector("linkset")!
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Get locale string
 | 
					 * Get locale string
 | 
				
			||||||
 * @param localString
 | 
					 * @param localString
 | 
				
			||||||
 * @param noReload
 | 
					 * @deprecated
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function getString(localString: string, noReload = false): string {
 | 
					export function getString(localString: string): string {
 | 
				
			||||||
  try {
 | 
					  let result = "";
 | 
				
			||||||
    return addon.data.locale?.stringBundle.GetStringFromName(localString);
 | 
					  let flag = false;
 | 
				
			||||||
  } catch (e) {
 | 
					  getStringAsync(localString)
 | 
				
			||||||
    if (!noReload) {
 | 
					    .then((value) => {
 | 
				
			||||||
      initLocale();
 | 
					      result = value;
 | 
				
			||||||
      return getString(localString, true);
 | 
					      flag = true;
 | 
				
			||||||
    }
 | 
					    })
 | 
				
			||||||
    return localString;
 | 
					    .catch((e) => {
 | 
				
			||||||
 | 
					      ztoolkit.log(e);
 | 
				
			||||||
 | 
					      flag = true;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  const t = new Date().getTime();
 | 
				
			||||||
 | 
					  while (!flag && t < new Date().getTime() - 3000) {
 | 
				
			||||||
 | 
					    // wait until the string is loaded
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get locale string async
 | 
				
			||||||
 | 
					 * @param localString
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export async function getStringAsync(localString: string): Promise<string> {
 | 
				
			||||||
 | 
					  // @ts-ignore
 | 
				
			||||||
 | 
					  return (await document.l10n.formatValue(localString)) || localString;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,4 @@
 | 
				
			|||||||
import { getString } from "./locale";
 | 
					export { isWindowAlive };
 | 
				
			||||||
 | 
					 | 
				
			||||||
export { isWindowAlive, localeWindow };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Check if the window is alive.
 | 
					 * Check if the window is alive.
 | 
				
			||||||
@ -10,57 +8,3 @@ export { isWindowAlive, localeWindow };
 | 
				
			|||||||
function isWindowAlive(win?: Window) {
 | 
					function isWindowAlive(win?: Window) {
 | 
				
			||||||
  return win && !Components.utils.isDeadWrapper(win) && !win.closed;
 | 
					  return win && !Components.utils.isDeadWrapper(win) && !win.closed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Locale the elements in window with the locale-target attribute.
 | 
					 | 
				
			||||||
 * Useful when the window is created dynamically.
 | 
					 | 
				
			||||||
 * @example
 | 
					 | 
				
			||||||
 * In HTML:
 | 
					 | 
				
			||||||
 * ```html
 | 
					 | 
				
			||||||
 * <div locale-target="innerHTML,title" title="elem.title">elem.text</div>
 | 
					 | 
				
			||||||
 * ```
 | 
					 | 
				
			||||||
 * In `addon/chrome/locale/en-US/addon.properties`:
 | 
					 | 
				
			||||||
 * ```properties
 | 
					 | 
				
			||||||
 * elem.text=Hello World
 | 
					 | 
				
			||||||
 * elem.title=Locale example
 | 
					 | 
				
			||||||
 * ```
 | 
					 | 
				
			||||||
 * In `addon/chrome/locale/zh-CN/addon.properties`:
 | 
					 | 
				
			||||||
 * ```properties
 | 
					 | 
				
			||||||
 * elem.text=你好世界
 | 
					 | 
				
			||||||
 * elem.title=多语言样例
 | 
					 | 
				
			||||||
 * ```
 | 
					 | 
				
			||||||
 * After locale:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * if locale is "en-US"
 | 
					 | 
				
			||||||
 * ```html
 | 
					 | 
				
			||||||
 * <div locale-target="innerHTML,title" title="Locale example">Hello World</div>
 | 
					 | 
				
			||||||
 * ```
 | 
					 | 
				
			||||||
 * else if locale is "zh-CN"
 | 
					 | 
				
			||||||
 * ```html
 | 
					 | 
				
			||||||
 * <div locale-target="innerHTML,title" title="多语言样例">你好世界</div>
 | 
					 | 
				
			||||||
 * ```
 | 
					 | 
				
			||||||
 * @param win
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
function localeWindow(win: Window) {
 | 
					 | 
				
			||||||
  Array.from(win.document.querySelectorAll("*[locale-target]")).forEach(
 | 
					 | 
				
			||||||
    (elem) => {
 | 
					 | 
				
			||||||
      const errorInfo = "Locale Error";
 | 
					 | 
				
			||||||
      const locales = elem.getAttribute("locale-target")?.split(",");
 | 
					 | 
				
			||||||
      locales?.forEach((key) => {
 | 
					 | 
				
			||||||
        const isProp = key in elem;
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
          const localeString = getString(
 | 
					 | 
				
			||||||
            (isProp ? (elem as any)[key] : elem.getAttribute(key)).trim() || ""
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
          isProp
 | 
					 | 
				
			||||||
            ? ((elem as any)[key] = localeString)
 | 
					 | 
				
			||||||
            : elem.setAttribute(key, localeString);
 | 
					 | 
				
			||||||
        } catch (error) {
 | 
					 | 
				
			||||||
          isProp
 | 
					 | 
				
			||||||
            ? ((elem as any)[key] = errorInfo)
 | 
					 | 
				
			||||||
            : elem.setAttribute(key, errorInfo);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user