Skip to content

Commit 3f89647

Browse files
authored
Merge pull request #16 from snipsnipsnip/l10n-toml
Prepare for l10n
2 parents d0b443f + 0e9ed9f commit 3f89647

23 files changed

Lines changed: 399 additions & 161 deletions

README.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ This add-on is not yet available on [addons.thunderbird.net](https://addons.thun
3939
3. Select `Install Add-on From File...` from the menu.
4040
4. Select downloaded `.xpi` file.
4141

42+
See [the help page in the Mozilla Support Center](https://support.mozilla.org/kb/installing-addon-thunderbird) for details.
43+
4244
### Build from source
4345

4446
Basically `yarn && yarn build`. See [CONTRIBUTING.md](./CONTRIBUTING.md) to get started.
@@ -99,7 +101,7 @@ gtClient -->|Updates| mailCompose
99101
* :nest_with_eggs: Start button on the toolbar
100102
* :nest_with_eggs: Edit plain text emails
101103
* :nest_with_eggs: Keyboard shortcuts
102-
* :construction: Roadmap and [Project board][proj]
104+
* :nest_with_eggs: Roadmap and [Project board][proj]
103105
* :no_entry: Non-bidirectional: Thunderbird becomes read-only while Ghostbird is active
104106
* :no_entry: No i18n: the UI is only in English*
105107
* :no_entry: Quirky when editing HTML emails
@@ -108,22 +110,22 @@ gtClient -->|Updates| mailCompose
108110
109111
### v0.1.0 (Alpha) - 2025 Q3
110112

111-
* :construction: Debug
113+
* :nest_with_eggs: [Debug](https://github.com/exteditor/ghostbird/issues/2)
112114

113115
### v0.x.x (Beta) - 2025 Q4
114116

115-
* :white_large_square: Website with some screenshot
116-
* :white_large_square: Basic option (at minimum, the port of the GhostText server)
117-
* :white_large_square: Prepare for i18n (Make texts translatable)
118-
* :white_large_square: Smoother editing of HTML emails
117+
* :white_large_square: [Website with some screenshot](https://github.com/exteditor/ghostbird/issues/5)
118+
* :construction: [Basic option (at minimum, the port of the GhostText server)](https://github.com/exteditor/ghostbird/issues/3)
119+
* :construction: [Prepare for i18n (Make texts translatable)](https://github.com/exteditor/ghostbird/issues/4)
120+
* :white_large_square: [Smoother editing of HTML emails](https://github.com/exteditor/ghostbird/issues/6)
119121

120122
### v1.0.0 (Stable) - 2026 Q2
121123

122-
* :white_large_square: Publish on AMO (functionally identical to the last beta)
124+
* :white_large_square: [Publish on AMO (functionally identical to the last beta)](https://github.com/exteditor/ghostbird/issues/9)
123125

124126
### v1.x.x (Stable) - 2026 Q4
125127

126-
* :white_large_square: Edit Address and Subject fields
128+
* :white_large_square: [Edit Address and Subject fields](https://github.com/exteditor/ghostbird/issues/8)
127129
* :white_large_square: Continue i18n (Add more languages)
128130
* :white_large_square: Support text editors that lack a GhostText add-on (e.g., Notepad)*
129131
* :white_large_square: Automate AMO release on GitHub
@@ -132,7 +134,7 @@ gtClient -->|Updates| mailCompose
132134
133135
### v2.x.x (Future)
134136

135-
* Proper implementation as a GhostText client
137+
* [Proper implementation as a GhostText client](https://github.com/exteditor/ghostbird/issues/10)
136138
* :white_large_square: Cursor and selection synchronization
137139
* :white_large_square: Bidirectional editing; changes in Thunderbird are reflected in the text editor
138140

doc/design.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,9 @@ thunderbird --> background & compose & options
223223
```
224224

225225
* All `src/*/index.ts` export everything in the same folder, so practically these folders are equivalent to modules.
226-
* `root/` contains entry points and depends on all other modules.
226+
* `root/` contains entry points and depends on all other modules except `test/`.
227227
* `ghosttext-session/` doesn't depend on other modules.
228-
* `ghosttext-*/` depends on `ghosttext`.
228+
* `ghosttext-adaptor/` depends on `ghosttext-runner/`, which depends on `ghosttext-session/`.
229229
* `root/` and `thunderbird/` can use Thunderbird API directly.
230230
* Other modules define subsets of the Thunderbird API they use as interfaces in `api.ts` files in their directories, which are implemented by `thunderbird/` modules.
231231

@@ -284,6 +284,29 @@ TL;DR: `root` module contains entry point and the [Composition Root][ploeh].
284284
* `test/startup.test.ts` contains tests to verify that all classes registered can be instantiated successfully.
285285
* See [FAQ](./faq-architectural.md) for some design decisions and justification.
286286

287+
```mermaid
288+
flowchart LR
289+
290+
need_instance["Need an<br>instance"]
291+
is_singleton{" "}
292+
is_singleton -->|isSingleton = true| singleton["Cache the<br>instance"]
293+
is_singleton -->|isSingleton = false| factory["Instantiate on<br>each request"]
294+
295+
prepare_argument{" "}
296+
prepare_argument -->|Need arguments| want_array{" "}
297+
prepare_argument -->|No argument<br>needed| Done@{shape: dbl-circ}
298+
want_array -->|wantArray = false| unique_instance["Resolve the<br>unique name"]
299+
want_array -->|wantArray = true| array_instances["Resolve all instances<br>having the same name"]
300+
is_alias{" "}
301+
is_alias <-->|Alias| resolve_alias["Resolve<br>the alias"] --> instantiate_class
302+
is_alias -->|Actual class| instantiate_class["Prepare<br>the instance"]
303+
304+
need_instance --> is_singleton
305+
singleton & factory --> prepare_argument
306+
unique_instance & array_instances --> is_alias
307+
instantiate_class --> need_instance
308+
```
309+
287310
## Links
288311

289312
* [GhostText protocol][protocol]

doc/faq-architectural.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
### How does automatic instantiation help with maintainability?
2222

23-
* It makes coding less boring by automating a necessary coding task that occurs often: passing objects around to call their methods. This task gets harder as the software grows (which correlates to the number of hops required). I like to think of it as being similar to generating a Makefile.
23+
* It makes coding less boring by automating a necessary coding task that occurs often: passing objects around to call their methods. I like to think of it as being similar to generating a Makefile. It's not a panacea, but I think it has some effect to extend lifespan of the code until it becomes unmaintainable due to the scale.
2424
* It nudges us to adhere to the [Dependency Inversion Principle][dip].
2525

2626
### How does DIP help with maintainability?
@@ -33,7 +33,6 @@
3333

3434
* Maybe, but I intend to maintain this project for a while, and this was the best solution I could devise to adapt to breaking Thunderbird API changes, which seem to [happen every few versions][tbchanges].
3535
* Also, adding DI after the fact tends to be very hard.
36-
* I think DI may be over-engineered, but [the DIP][dip] is still valuable.
3736
* We might drop the autowiring thing and instantiate manually with `new` if the project ends up being stable enough. The practice of initializing everything in `startup.ts` would [still be useful][ploeh], though. It's possible to drop autowiring without [giving up DIP][ploeh2].
3837

3938
### It looks like not using a dependency injection library. Why are you reinventing the wheel?

ext/_locales/en/messages.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

locales.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This file contains translations for various messages Ghostbird shows.
2+
# The format is as follows:
3+
#
4+
# [<message_id>]
5+
# <language> = "<translated message>"
6+
#
7+
# See https://pontoon.mozilla.org/projects/thunderbirdnet/ for canonical terms like "email".
8+
9+
[manifest_name]
10+
# Full name of the extension.
11+
en = "Ghostbird - GhostText for Thunderbird"
12+
ja = "Ghostbird - Thunderbird用GhostText"
13+
14+
[manifest_description]
15+
# Description of the extension.
16+
en = "Use your favorite text editor to compose emails"
17+
ja = "好きなテキストエディタでメールを編集"
18+
19+
[manifest_commands_start_ghostbird_description]
20+
# Description of the shortcut key to start Ghostbird.
21+
en = "Connect to the text editor"
22+
ja = "テキストエディタに接続"
23+
24+
[manifest_commands_stop_ghostbird_description]
25+
# Description of the shortcut key to stop Ghostbird.
26+
en = "Disconnect from the text editor"
27+
ja = "テキストエディタから切断"
28+
29+
[manifest_commants_toggle_ghostbird_description]
30+
# Description of the shortcut key to toggle Ghostbird.
31+
en = "Toggle connection with the text editor"
32+
ja = "テキストエディタとの接続を切り替え"

manifest_template.json

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
{
22
"manifest_version": 3,
3-
"name": "Ghostbird - GhostText for Thunderbird",
3+
"name": "__MSG_manifest_name__",
44
"short_name": "Ghostbird",
5-
"description": "Use your favorite text editor to compose emails in Thunderbird",
5+
"description": "__MSG_manifest_description__",
66
"version": "$version$",
77
"homepage_url": "$homepage_url$",
8+
"version_name": "$version_name$",
89
"default_locale": "en",
910
"author": "snipsnipsnip",
11+
"browser_specific_settings": {
12+
"gecko": {
13+
"id": "@ghostbird.exteditor.github.io",
14+
"strict_min_version": "128.0"
15+
}
16+
},
1017
"permissions": [
1118
"alarms",
1219
"storage",
@@ -23,24 +30,18 @@
2330
"icons": {
2431
"96": "blue.svg"
2532
},
26-
"browser_specific_settings": {
27-
"gecko": {
28-
"id": "@ghostbird.exteditor.github.io",
29-
"strict_min_version": "128.0"
30-
}
31-
},
3233
"commands": {
33-
"start-ghostbird": {
34-
"description": "Start Ghostbird and connect to the GhostText server",
34+
"start_ghostbird": {
35+
"description": "__MSG_manifest_commands_start_ghostbird_description__",
3536
"suggested_key": {
36-
"default": "Ctrl+E"
37+
"default": "Ctrl+Shift+H"
3738
}
3839
},
39-
"stop-ghostbird": {
40-
"description": "Disconnect from the GhostText server and Stop Ghostbird. (Set the same shortcut as 'Start Ghostbird' to toggle)",
41-
"suggested_key": {
42-
"default": "Ctrl+E"
43-
}
40+
"stop_ghostbird": {
41+
"description": "__MSG_manifest_commands_stop_ghostbird_description__"
42+
},
43+
"toggle_ghostbird": {
44+
"description": "__MSG_manifest_commands_toggle_ghostbird_description__"
4445
}
4546
},
4647
"background": {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"devDependencies": {
5959
"@biomejs/biome": "2.2.0",
6060
"@std/text": "jsr:^1.0.16",
61+
"@std/toml": "jsr:^1.0.10",
6162
"@types/node": "^24.3.0",
6263
"@types/thunderbird-webext-browser": "^127.0.0",
6364
"barrelsby": "^2.8.1",

src/app-background/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { IComposeWindow } from "src/ghosttext-adaptor/api"
33
export type { IGhostServerPort } from "src/ghosttext-adaptor/api"
44

55
/** IDs of shortcut keys. Must be in sync with ones in manifest.json */
6-
export type CommandId = "start-ghostbird" | "stop-ghostbird"
6+
export type CommandId = "start_ghostbird" | "stop_ghostbird" | "toggle_ghostbird"
77

88
/** Queries current shortcut key config */
99
export interface ICommandConfig {

src/app-background/background_event_router.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { IComposeWindow } from "src/ghosttext-adaptor/api"
12
import type { CommandId, ICommandConfig, IComposeWindowDetector, ITab } from "./api"
23
import type { ComposeActionNotifier } from "./compose_action_notifier"
34

@@ -24,11 +25,17 @@ export class BackgroundEventRouter {
2425
return this.composeActionNotifier.toggle(composeTab)
2526
}
2627

28+
return this.runCommand(command, composeTab)
29+
}
30+
31+
private runCommand(command: string, composeTab: IComposeWindow): Promise<void> {
2732
switch (command as CommandId) {
28-
case "start-ghostbird":
33+
case "start_ghostbird":
2934
return this.composeActionNotifier.start(composeTab)
30-
case "stop-ghostbird":
35+
case "stop_ghostbird":
3136
return this.composeActionNotifier.stop(composeTab)
37+
case "toggle_ghostbird":
38+
return this.composeActionNotifier.toggle(composeTab)
3239
}
3340
// We don't handle default here so that tsc checks for exhaustiveness
3441
}

src/app-background/compose_action_notifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class ComposeActionNotifier {
2828
}
2929
}
3030

31-
stop(tab: IComposeWindow): void {
31+
async stop(tab: IComposeWindow): Promise<void> {
3232
this.close(tab, this.runners.get(tab.tabId))
3333
}
3434

0 commit comments

Comments
 (0)