Skip to content

Commit

Permalink
feat: Localize sync progress window (#576)
Browse files Browse the repository at this point in the history
* refactor: Use `FluentMessageId` type for remaining l10n IDs

* feat: Localize sync progress window

* refactor: Allow parameterization of l10n types
  • Loading branch information
dvanoni committed Sep 14, 2024
1 parent f9c40a2 commit 13462bd
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 25 deletions.
6 changes: 5 additions & 1 deletion src/content/prefs/notero-pref.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FluentMessageId } from '../../locale/fluent-types';
import { MissingPrefError } from '../errors';

export enum NoteroPref {
Expand All @@ -18,7 +19,10 @@ export enum PageTitleFormat {
itemTitle = 'itemTitle',
}

export const PAGE_TITLE_FORMAT_L10N_IDS: Record<PageTitleFormat, string> = {
export const PAGE_TITLE_FORMAT_L10N_IDS: Record<
PageTitleFormat,
FluentMessageId
> = {
[PageTitleFormat.itemAuthorDateCitation]:
'notero-page-title-format-item-author-date-citation',
[PageTitleFormat.itemCitationKey]:
Expand Down
3 changes: 2 additions & 1 deletion src/content/prefs/preferences.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import type { createRoot } from 'react-dom/client';

import { FluentMessageId } from '../../locale/fluent-types';
import { LocalizableError } from '../errors';
import { getNotionClient } from '../sync/notion-client';
import {
Expand All @@ -26,7 +27,7 @@ type ReactDOMClient = typeof ReactDOM & { createRoot: typeof createRoot };

type MenuItem = {
disabled?: boolean;
l10nId?: string;
l10nId?: FluentMessageId;
label?: string;
value: string;
};
Expand Down
3 changes: 2 additions & 1 deletion src/content/services/ui-manager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { FluentMessageId } from '../../locale/fluent-types';
import { createXULElement, logger } from '../utils';

import type { EventManager } from './event-manager';
Expand Down Expand Up @@ -103,7 +104,7 @@ export class UIManager implements Service {
parentId,
window,
}: {
l10nId: string;
l10nId: FluentMessageId;
onCommand: (event: Event) => void;
parentId: string;
window: Zotero.ZoteroWindow;
Expand Down
24 changes: 17 additions & 7 deletions src/content/sync/progress-window.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
import { FluentMessageId } from '../../locale/fluent-types';

export class ProgressWindow {
private readonly itemCount: number;
private readonly itemProgress: Zotero.ProgressWindow.ItemProgress;
private itemProgress!: Zotero.ProgressWindow.ItemProgress;
private readonly l10n: L10n.Localization<FluentMessageId>;
private readonly progressWindow: Zotero.ProgressWindow;

public constructor(itemCount: number) {
public constructor(itemCount: number, window: Window) {
this.itemCount = itemCount;
this.l10n = window.document.l10n;
this.progressWindow = new Zotero.ProgressWindow({ window });
}

this.progressWindow = new Zotero.ProgressWindow();
this.progressWindow.changeHeadline('Syncing items to Notion…');
public async show() {
const headline = await this.l10n.formatValue('notero-progress-headline');
this.progressWindow.changeHeadline(headline || 'Syncing items to Notion…');
this.progressWindow.show();

this.itemProgress = new this.progressWindow.ItemProgress('document', '');
}

public updateText(step: number) {
this.itemProgress.setText(`Item ${step} of ${this.itemCount}`);
public async updateText(step: number) {
const args = { step, total: this.itemCount };
const message =
(await this.l10n.formatValue('notero-progress-item', args)) ||
`Item ${step} of ${this.itemCount}`;
this.itemProgress.setText(message);
}

public updateProgress(step: number) {
Expand Down
5 changes: 3 additions & 2 deletions src/content/sync/sync-job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export async function performSyncJob(
const items = Zotero.Items.get(Array.from(itemIDs));
if (!items.length) return;

const progressWindow = new ProgressWindow(items.length);
const progressWindow = new ProgressWindow(items.length, window);
await progressWindow.show();

try {
const syncJob = await prepareSyncJob({ items, progressWindow, window });
Expand Down Expand Up @@ -161,7 +162,7 @@ class SyncJob {
);
logger.debug(item.getDisplayTitle());

this.progressWindow.updateText(step);
await this.progressWindow.updateText(step);

try {
if (item.isNote()) {
Expand Down
5 changes: 5 additions & 0 deletions src/locale/en-US/notero.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ notero-preferences-sync-on-modify-items =
notero-preferences-sync-notes =
.label = Sync notes
## Progress window

notero-progress-headline = Syncing items to Notion…
notero-progress-item = Item { $step } of { $total }
## Errors

notero-error-missing-notion-database = Notion database not selected. Please select your database in Notero preferences.
Expand Down
26 changes: 13 additions & 13 deletions types/l10n.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ declare namespace L10n {
[key: string]: string | number;
}

interface L10nIdArgs {
id: string | null;
interface L10nIdArgs<I extends string> {
id: I | null;
args?: L10nArgs | null;
}

type L10nKey = string | L10nIdArgs;
type L10nKey<I extends string> = I | L10nIdArgs<I>;

interface AttributeNameValue {
name: string;
Expand All @@ -27,7 +27,7 @@ declare namespace L10n {
/**
* @see https://searchfox.org/mozilla-esr115/source/dom/webidl/Localization.webidl
*/
interface Localization {
interface Localization<I extends string = string> {
(
resourceIds: L10nResourceId[],
sync?: boolean,
Expand All @@ -39,25 +39,25 @@ declare namespace L10n {

removeResourceIds(resourceIds: L10nResourceId[]): number;

formatValue(id: string, args?: L10nArgs): Promise<string | null>;
formatValue(id: I, args?: L10nArgs): Promise<string | null>;

formatValues(keys: L10nKey[]): Promise<(string | null)[]>;
formatValues(keys: L10nKey<I>[]): Promise<(string | null)[]>;

formatMessages(keys: L10nKey[]): Promise<(L10nMessage | null)[]>;
formatMessages(keys: L10nKey<I>[]): Promise<(L10nMessage | null)[]>;

setAsync(): void;

formatValueSync(id: string, args?: L10nArgs): string | null;
formatValueSync(id: I, args?: L10nArgs): string | null;

formatValuesSync(keys: L10nKey[]): (string | null)[];
formatValuesSync(keys: L10nKey<I>[]): (string | null)[];

formatMessagesSync(keys: L10nKey[]): (L10nMessage | null)[];
formatMessagesSync(keys: L10nKey<I>[]): (L10nMessage | null)[];
}

/**
* @see https://searchfox.org/mozilla-esr115/source/dom/webidl/DOMLocalization.webidl
*/
interface DOMLocalization extends Localization {
interface DOMLocalization<I extends string = string> extends Localization<I> {
connectRoot(element: Node): void;

disconnectRoot(element: Node): void;
Expand All @@ -66,9 +66,9 @@ declare namespace L10n {

resumeObserving(): void;

setAttributes(element: Element, id: string, args?: object): void;
setAttributes(element: Element, id: I, args?: object): void;

getAttributes(element: Element): L10nIdArgs;
getAttributes(element: Element): L10nIdArgs<I>;

setArgs(element: Element, args?: object): void;

Expand Down

0 comments on commit 13462bd

Please sign in to comment.