Skip to content

Commit 56b17f2

Browse files
authored
Merge cbde636 into e2541ee
2 parents e2541ee + cbde636 commit 56b17f2

9 files changed

Lines changed: 344 additions & 110 deletions

File tree

projectDocs/dev/developerGuide/developerGuide.md

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -949,9 +949,11 @@ Then the handler needs to be registered - preferably in the constructor of your
949949
addonHandler.isCLIParamKnown.register(processArgs)
950950
## Packaging Code as NVDA Add-ons {#Addons}
951951

952-
To make it easy for users to share and install plugins, drivers and braille translation tables, they can be packaged in to a single NVDA add-on package which the user can then install into a copy of NVDA via the Add-on Store found under Tools in the NVDA menu.
952+
Add-ons make it easy for users to share and install plugins, drivers, speech symbol dictionaries and braille translation tables.
953+
They can be packaged in to a single NVDA add-on package, which the user can then install into a copy of NVDA via the Add-on Store found under Tools in the NVDA menu.
953954
Add-on packages are only supported in NVDA 2012.2 and later.
954-
An add-on package is simply a standard zip archive with the file extension of "`nvda-addon`" which contains a manifest file, optional install/uninstall code and one or more directories containing plugins, drivers and/or and braille translation tables.
955+
An add-on package is simply a standard zip archive with the file extension of "`nvda-addon`".
956+
It can contain a manifest file, install/uninstall code and directories containing plugins, drivers, speech symbol dictionaries and braille translation tables.
955957

956958
### Non-ASCII File Names in Zip Archives {#nonASCIIFileNamesInZip}
957959

@@ -1013,21 +1015,23 @@ The lastTestedNVDAVersion field in particular is used to ensure that users can b
10131015
It allows the add-on author to make an assurance that the add-on will not cause instability, or break the users system.
10141016
When this is not provided, or is less than the current version of NVDA (ignoring minor point updates e.g. 2018.3.1) then the user will be warned not to install the add-on.
10151017

1016-
The manifest can also specify information regarding the additional braille translation tables provided by the add-on.
1017-
Please refer to the [braille translation tables section](#BrailleTables) later on in this document.
1018+
The manifest can also specify information regarding the additional speech symbol dictionaries and braille translation tables provided by the add-on.
1019+
Please refer to the [speech symbol dictionaries](#AddonSymbolDictionaries) and [braille translation tables](#BrailleTables) sections.
10181020

10191021
#### An Example Manifest File {#manifestExample}
1020-
--- start ---
1021-
name = "myTestAddon"
1022-
summary = "Cool Test Add-on"
1023-
version = "1.0.0"
1024-
description = "An example add-on showing how to create add-ons!"
1025-
author = "Michael Curran <mick@example.com>"
1026-
url = "https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/addons.md"
1027-
docFileName = "readme.html"
1028-
minimumNVDAVersion = "2021.1"
1029-
lastTestedNVDAVersion = "2022.3.3"
1030-
--- end ---
1022+
1023+
```ini
1024+
name = "myTestAddon"
1025+
summary = "Cool Test Add-on"
1026+
version = "1.0.0"
1027+
description = "An example add-on showing how to create add-ons!"
1028+
author = "Michael Curran <mick@example.com>"
1029+
url = "https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/addons.md"
1030+
docFileName = "readme.html"
1031+
minimumNVDAVersion = "2021.1"
1032+
lastTestedNVDAVersion = "2022.3.3"
1033+
```
1034+
10311035
### Plugins and Drivers {#pluginsAndDrivers}
10321036

10331037
The following plugins and drivers can be included in an add-on:
@@ -1036,6 +1040,7 @@ The following plugins and drivers can be included in an add-on:
10361040
* Braille display drivers: Place them in a brailleDisplayDrivers directory in the archive.
10371041
* Global plugins: Place them in a globalPlugins directory in the archive.
10381042
* Synthesizer drivers: Place them in a synthDrivers directory in the archive.
1043+
* [Speech symbol dictionaries](#AddonSymbolDictionaries): Place them in the directory for one or more [locales](#localizingAddons) with a file name of `symbols-<name>.dic`, e.g. `locale\en\symbols-greek.dic`.
10391044
* [Braille translation tables](#BrailleTables): Place them in a brailleTables directory in the archive.
10401045

10411046
### Optional install / Uninstall code {#installUninstallCode}
@@ -1067,6 +1072,7 @@ This directory should contain directories for each language it supports, using t
10671072

10681073
Each of these language directories can contain a locale-specific manifest file called manifest.ini, which can contain a small subset of the manifest fields for translation.
10691074
These fields are summary and description.
1075+
You can also override the `displayName` field for speech symbol dictionaries and braille translation tables.
10701076
All other fields will be ignored.
10711077

10721078
#### Locale-specific Messages {#localeMessages}
@@ -1077,6 +1083,47 @@ To allow plugins in your add-on to access gettext message information via calls
10771083
This function cannot be called in modules that do not belong to an add-on, e.g. in a scratchpad subdirectory.
10781084
For more information about gettext and NVDA translation in general, please read the [Translating NVDA page](https://github.com/nvaccess/nvda/blob/master/projectDocs/translating/readme.md)
10791085

1086+
#### Speech symbol dictionaries {#AddonSymbolDictionaries}
1087+
1088+
You can provide custom speech symbol dictionaries in add-ons to improve symbol pronunciation.
1089+
The process to create custom speech symbol dictionaries is very similar to that of the [translation process of existing symbols](#symbolPronunciation).
1090+
Note that [complex symbols](#complexSymbols) are not supported.
1091+
1092+
Custom dictionaries must be placed in a language directory and have a filename in the form `symbols-<name>.dic`, where `<name>` is the name that has to be provided in the add-ons manifest.
1093+
All locales implicitly inherit the symbol information for English, though any of this information can be overridden for specific locales.
1094+
1095+
When adding a dictionary not marked as mandatory, some information must be provided such as its display name, since it should be shown in the speech category of the settings dialog.
1096+
A dictionary can also be marked mandatory, in which case it is always enabled with the add-on.
1097+
When an add-on ships with dictionaries, this information is included in its manifest in the optional `symbolDictionaries` section.
1098+
For example:
1099+
1100+
```ini
1101+
[symbolDictionaries]
1102+
[[greek]]
1103+
displayName = Greek
1104+
mandatory = false
1105+
1106+
[[hebrew]]
1107+
displayName = Biblical Hebrew
1108+
mandatory = true
1109+
```
1110+
1111+
In the above example, `greek` is a dictionary that is optional and will be listed in the speech category of NVDA's settings dialog under the "Extra dictionaries for character and symbol processing" setting.
1112+
Its file will be stored as `locale\en\symbols-greek.dic`, whereas French translations of the symbols are stored in `locale\fr\symbols-greek.dic`.
1113+
When using NVDA in French, symbols that aren't defined in the French dictionary inherit the symbol information for English.
1114+
1115+
Also in the example, the `hebrew` dictionary is marked mandatory and will therefore always be enabled as long as the add-on is active.
1116+
Its file will be stored as `locale\en\symbols-hebrew.dic`, whereas French translations of the symbols are stored in `locale\fr\symbols-hebrew.dic`.
1117+
1118+
Note that for the display name of the dictionary to be translated, an entry should be added to a [locale manifest](#localeManifest).
1119+
For example, add the following to `locale\fr\manifest.ini`:
1120+
1121+
```ini
1122+
[symbolDictionaries]
1123+
[[hebrew]]
1124+
displayName = Hébreu Biblique
1125+
```
1126+
10801127
### Add-on Documentation {#AddonDoc}
10811128

10821129
Documentation for an add-on should be placed in a doc directory in the archive.
@@ -1121,6 +1168,15 @@ Providing a custom table, whether it has the same file name as a standard table
11211168
The only exception to this rule applies to tables that are included within other tables.
11221169
While they don't have to be included in the manifest of the add-on, they can only be included from other tables that are part of the same add-on.
11231170

1171+
Note that for the display name of the table to be translated, an entry should be added to a [locale manifest](#localeManifest).
1172+
For example, add the following to `locale\fr\manifest.ini`:
1173+
1174+
```ini
1175+
[brailleTables]
1176+
[[no-no-8dot.utb]]
1177+
displayName = Norvégien Braille informatique 8 points - Remplacement
1178+
```
1179+
11241180
Custom tables can also be placed in the brailleTables subdirectory of the scratchpad directory.
11251181
In this case, the table metadata can be placed in a `manifest.ini` file in the root of the scratchpad in the exact same format as the example above.
11261182
Basically, this means that, whether using an add-on or the scratchpad, the requirements and implementation steps are equal.

source/addonHandler/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,13 @@ class AddonManifest(ConfigObj):
10141014
input = boolean(default=true)
10151015
output = boolean(default=true)
10161016
1017+
# Symbol Pronunciation
1018+
[symbolDictionaries]
1019+
# The key is the symbol dictionary file name (not the full path)
1020+
[[__many__]]
1021+
displayName = string()
1022+
mandatory = boolean(default=false)
1023+
10171024
# NOTE: apiVersion:
10181025
# EG: 2019.1.0 or 0.0.0
10191026
# Must have 3 integers separated by dots.
@@ -1054,6 +1061,10 @@ def __init__(self, input, translatedInput=None):
10541061
value = tableConfig.get("displayName")
10551062
if value:
10561063
self["brailleTables"][fileName]["displayName"] = value
1064+
for fileName, dictConfig in self._translatedConfig.get("symbolDictionaries", {}).items():
1065+
value = dictConfig.get("displayName")
1066+
if value:
1067+
self["symbolDictionaries"][fileName]["displayName"] = value
10571068

10581069
@property
10591070
def errors(self):

0 commit comments

Comments
 (0)