Fix creating user guide with l10nUtil (#19842)
Fixes #19814
### Summary of the issue:
Using `l10nUtil` to build the user guide does not work from frozen
copies of NVDA.
### Description of user facing changes:
Translators can once again use l10nUtil to build the user guide with
installed or portable copies of NVDA.
### Description of developer facing changes:
None
### Description of development approach:
Added a py2exe hook for latex2mathml.
latex2mathml relies on a data file, `unimathsymbols.txt`, which is
located along side its source files. There are two problems with this:
1. py2exe doesn't include this file, as it is not a python file.
2. latex2mathml is not aware it is being run from a zip file, so
attempts to load this file from a nonexistant location (treating
`library.zip` as a directory).
To work around this, explicitly include `unimathsymbols.txt` in frozen
distributions, in a `latex2mathml` directory alongside `library.zip`,
and rewrite `latex2mathml.symbols_parser` to set `SYMBOLS_FILE` to this
new path. The approach here is based on the [hooks that ship with
py2exe](https://github.com/py2exe/py2exe/blob/v0.14.0.0/py2exe/hooks.py).
### Testing strategy:
From a clean checkout, built a portable copy of NVDA (1), cleaned the
French user guide directory (2), then built the user guide using the
binary l10nUtil (3). Checked that math was present in this
`user_docs/fr/userGuide.html`.
```ps1
PS D:\projects\nvda-beta> uv sync
Using CPython 3.13.12 interpreter at: C:\Users\SaschaCowley\AppData\Local\Python\pythoncore-3.13-64\python.exe
Creating virtual environment at: .venv
Resolved 106 packages in 15ms
...
+ win32-setctime==1.2.0
+ wrapt==2.0.1
+ wxpython==4.2.4
PS D:\projects\nvda-beta> ./scons dist -j1 # (1)
scons: Reading SConscript files ...
Warning: Building with 1 concurrent job while 16 CPU threads are available. Running SCONS with the parameter '-j16' may lead to a faster build. Running SCONS with parameter '--all-cores' will automatically pick all available cores.
scons: done reading SConscript files.
...
Delete("source\__pycache__\_buildVersion.cpython-313.pyc")
uninstaller\uninstGen.exe
scons: done building targets.
PS D:\projects\nvda-beta> git clean -xf user_docs/fr/ # (2)
Removing user_docs/fr/changes.html
Removing user_docs/fr/changes.md
Removing user_docs/fr/changes.md.sub
...
Removing user_docs/fr/userGuide.html
Removing user_docs/fr/userGuide.md
Removing user_docs/fr/userGuide.md.sub
PS D:\projects\nvda-beta> ./dist/l10nUtil.exe xliff2html -t userGuide user_docs\fr\userGuide.xliff user_docs\fr\userGuide.html # (3)
Detected language fr for xliff file user_docs\fr\userGuide.xliff, source=False
Generating markdown file C:\Users\SASCHA~1\AppData\Local\Temp\tmpoc3xc5nr.md from user_docs\fr\userGuide.xliff...
Generated markdown file with 6042 total lines, 4068 translatable strings, and 3756 translated strings. Ignoring 312 bad translated strings
Converting userGuide (lang='fr') at C:\Users\SASCHA~1\AppData\Local\Temp\tmpoc3xc5nr.md to user_docs\fr\userGuide.html
PS D:\projects\nvda-beta>
```
### Known issues with pull request:
This approach is reliant on the structure of latex2mathml. An update to
this dependency may break it. However, this shouldn't have a production
impact, as the py2exe hook will cause the build to fail if it is unable
to patch latex2mathml, meaning we should know about the breakage before
it becomes a runtime failure.