Conversation
DescriptionThis PR allows to create an executable to be used in the following projects available at Crowdin:
Development approachMethods available in the Crowdin API client have been used to upload source files to Crowdin, and to get the files available in the project, updating a json file progressively, i.e., when the user needs to know a file ID to run a command from the created executable, this utility checks the json file corresponding to the project ID (like NVDA, nvdaAddons etc.), and, if the file ID is not found, it request the File ID to the API. To avoid issues due to the size of the list of available files, we filted retrieved files to get just the needed ID, to update the json file in a progressive way appending needed file IDS. Another significant difference is that the crowdinSync module has been removed. Instead, we use the Crowdin API client to add or update source files. There are other commands available. |
|
@seanbudd , I've created this PR to allow NV Access to review proposed differences. Feel free to review or to close this in case you prefer a different approach. |
|
Command to create the executable file, which will be placed in a dist subfolder: After creating the executable, find it in /dist/l10nUtil.exe. |
seanbudd
left a comment
There was a problem hiding this comment.
I'm very confused about the large amount of behaviour changes here. Can you please make a more detailed PR description outlining these changes, and consider splitting up this PR into smaller pieces?
source/md2html.py
Outdated
| # External links will open in a new tab, and title will be set to the link text | ||
| "markdown_link_attr_modifier", | ||
| # Adds links to GitHub authors, issues and PRs | ||
| "mdx_gh_links", |
There was a problem hiding this comment.
what happened to LaTeX2MathMLExtension?
There was a problem hiding this comment.
Sorry, all changes of this file are accidental. I wanted to change just l10nUtil, and remove crowdinSync
source/md2html.py
Outdated
| if "math" not in allowedAttributes: | ||
| allowedAttributes["math"] = set() | ||
| allowedAttributes["math"].add("display") | ||
|
|
||
| return allowedAttributes | ||
|
|
||
|
|
||
| def _attributeFilter(tag: str, attr: str, value: str) -> str | None: | ||
| # Specifying display=inline is redundant | ||
| if tag == "math" and attr == "display": | ||
| return value if value == "block" else None | ||
| return value | ||
|
|
||
|
|
||
| def _createTagFilter() -> set[str]: | ||
| import nh3 | ||
|
|
||
| return nh3.ALLOWED_TAGS | {"math", "mrow", "mfrac", "mi", "mn", "mo", "msub"} | ||
|
|
source/md2html.py
Outdated
| }, | ||
| "pymdownx.superfences": { | ||
| "preserve_tabs": True, | ||
| }, |
There was a problem hiding this comment.
are you sure this can be removed?
pyproject.toml
Outdated
| reportDeprecated = false # 1834 errors | ||
|
|
||
| # Can be enabled by generating type stubs for modules via pyright CLI | ||
| reportMissingTypeStubs = false | ||
|
|
||
| # Bad rules | ||
| # These are roughly sorted by compliance to make it easier for devs to focus on enabling them. | ||
| # Errors were last checked Feb 2025. | ||
| # 1-50 errors | ||
| reportUnsupportedDunderAll = false # 2 errors | ||
| reportAbstractUsage = false # 3 errors | ||
| reportUntypedBaseClass = false # 4 errors | ||
| reportOptionalIterable = false # 5 errors | ||
| reportCallInDefaultInitializer = false # 6 errors | ||
| reportInvalidTypeArguments = false # 7 errors | ||
| reportUntypedNamedTuple = false # 11 errors | ||
| reportRedeclaration = false # 12 errors | ||
| reportOptionalCall = false # 16 errors | ||
| reportConstantRedefinition = false # 18 errors | ||
| reportWildcardImportFromLibrary = false # 26 errors | ||
| reportIncompatibleVariableOverride = false # 28 errors | ||
| reportInvalidTypeForm = false # 38 errors | ||
|
|
||
|
|
||
| # 50-100 errors | ||
| reportGeneralTypeIssues = false # 53 errors | ||
| reportOptionalOperand = false # 59 errors | ||
| reportUnnecessaryComparison = false # 67 errors | ||
| reportFunctionMemberAccess = false # 80 errors | ||
| reportUnnecessaryIsInstance = false # 88 errors | ||
| reportUnusedFunction = false # 97 errors | ||
| reportImportCycles = false # 99 errors | ||
| reportUnusedImport = false # 113 errors | ||
| reportUnusedVariable = false # 147 errors | ||
|
|
||
| # 100-1000 errors | ||
| reportOperatorIssue = false # 102 errors | ||
| reportAssignmentType = false # 103 errors | ||
| reportReturnType = false # 104 errors | ||
| reportPossiblyUnboundVariable = false # 126 errors | ||
| reportMissingSuperCall = false # 159 errors | ||
| reportUninitializedInstanceVariable = false # 179 errors | ||
| reportUnknownLambdaType = false # 196 errors |
There was a problem hiding this comment.
can't we make these true here?
There was a problem hiding this comment.
Now all is true. Let's see what errors. Now replying from the new interface when using the files changed link to review and leave comments seems not to be accessible or at least I don't find it, though the interface itself is nice. So I'm switching from files changed to the main conversation. Sorry if I reply to the wrong comment, but this is for pyproject.toml.
| @@ -1,89 +0,0 @@ | |||
| # A part of NonVisual Desktop Access (NVDA) | |||
There was a problem hiding this comment.
According to my tests, this file wouldn't be necessary.
There was a problem hiding this comment.
how else will we sync with crowdin in NVDA and the addontemplate?
There was a problem hiding this comment.
For now the uploadSourceFile command is just available for the nvdaAddons project since I was not sure if you would prefer to use crowdinSync or not. I can create a separate pull request, but this may take some days.
There was a problem hiding this comment.
I'm not sure I understand. I think we want to ensure all the shared code between NVDA and addonTemplate is in the l10nUtil. Don't we need uploadSourceFile from this file in both repos?
There was a problem hiding this comment.
No, uploadSourceFile is a command added to the l10nUtil file without using custom code, but using the standard methods from the API. I thought that this would be more compact and maintainable. So when creating the executable, uploadSourceFile is just another command. But I didn't know if you would like to use crowdinSync or just my approach, so I have added this just for the nvdaAddons project. I'll make it available for any other projects and you may want to test it with NVDA.
|
can you please make sure to review the diff and ensure only intended changes are included. moving functions and blocks around for no clear reason makes reviewing the diff harder. |
|
Sean wrote:
I think it's done now. I've reviewed diffs in l10nUtil.py with the -w flag to ignore tabs and spaces, since nany differences are caused to format. |
pyproject.toml
Outdated
|
|
||
| [project] | ||
| name = "nvdaL10n" | ||
| name = "nvdal10n" |
There was a problem hiding this comment.
| name = "nvdal10n" | |
| name = "nvdaL0n" |
There was a problem hiding this comment.
I assume that you mean nvdaL10n, right?
pyproject.toml
Outdated
| description = "Utilities for translations in NVDA and the add-on template" | ||
| maintainers = [ | ||
| {name = "NV Access", email = "info@nvaccess.org"}, | ||
| {name = "Noelia Ruiz Martínez", email = "nrm1977@gmail.com"}, |
There was a problem hiding this comment.
can we keep this as NV Access?
pyproject.toml
Outdated
| # Bad rules | ||
| # These are sorted alphabetically and should be enabled and moved to compliant rules section when resolved. | ||
| lint = [ | ||
| "ruff==0.8.1", | ||
| "pre-commit==4.0.1", | ||
| "pyright==1.1.396", | ||
| ] |
There was a problem hiding this comment.
can this be moved with other dependencies and the comment removed?
pyproject.toml
Outdated
| venvPath = ".venv" | ||
| venvPath = "../nvda/.venv" |
There was a problem hiding this comment.
I think we should be using the venv set up for the add-on template. this change should be undone
pyproject.toml
Outdated
| # Tell pyright where to load python code from | ||
| extraPaths = [ | ||
| "../addon", | ||
| "../nvda/source", | ||
| ] |
pyproject.toml
Outdated
|
|
||
| [project.optional-dependencies] | ||
| windows-packaging = [ | ||
| "py2exe==0.11.1.0", |
source/l10nUtil.py
Outdated
|
|
||
|
|
||
| _crowdinClient = None | ||
| _crowdinProjectId = 598017 |
There was a problem hiding this comment.
let's remove this, and only use the project ID passed in via CLI.
also, sorry to make things more complicated, but I was thinking this might be the best way to handle the different configs required for different projects.
We could use a YAML file as config that includes the project ID and a mapping of file IDs and file names.
We could include YAML config files for both the add-on template and NVDA in the distribution of this. That way instead people could just do nvdaL10nUtil.exe -c [nvda.yaml|addon.yaml] [command] <file>. This also means its more easily customisable for other projects. I'm worried getFiles won't work due to the aliases we need for .po/.pot
There was a problem hiding this comment.
OK. Then should we use _crowdinProjectId = None? to set the global variable according to the -i flag? Should we encapsulate _crowdinClient and _crowdinProjectId in a dataclass named, for example, ClientVariables or something? For the yaml file, can you provide the exact structure? Should we try to dump values to cache them from getFiles, like done with json files previously? I guess that yaml is more readable than json and easy to write.
There was a problem hiding this comment.
I think we should encapsulate it into a dataclass, one which can be loaded from the yaml config file.
JSON is also fine for config, either is good to me.
e.g.
{
"crowdinProjectId": 93,
"files": {"nvda.po": 12}
}
There was a problem hiding this comment.
Perhaps the yaml file is easier to edit. Should we restore the ability to update the yaml (or json) file from the getFiles function? Otherwise, I don't know how these files will be created or updated.
There was a problem hiding this comment.
The idea is to create the config files manually as maintainers, and ship the config files with the l10n exe
There was a problem hiding this comment.
ah okay - do you think this could be generated via a command?
There was a problem hiding this comment.
I think this cannot be generated via a single command, since, if we call getFiles and try to write the full list in a yaml file, the list may be too long and we may have issues with the connection. I would restore the previous behavior of the getFiles function if you agree, i. e., trying to update the yaml file when getFiles is called with the filter parameter, so that file ids are added progressively. Then, the getFiles function may try to retrieve files from the yaml file before using the Crowdin API, and just if a refresh parameter is set to True, or if files aren't found in the yaml file, the Crowdin API is used. Please let me know if this is the right approach.
There was a problem hiding this comment.
I'm suggesting we generate config files when creating l10nUtil.exe not when running it for the first time. However, I imagine this may cause problems, as people would need to sync with the latest config file somehow from their add-on repository
There was a problem hiding this comment.
My suggestion would be to create configuration files when translators use this tool for add-ons, and when the exe file is created for NVDA. There are a lot of add-ons, but NVDA has just a few files that can be reflected in the yaml file. If you want, I can design a prototype, perhaps in a different PR or just here.
There was a problem hiding this comment.
that sounds good to me. We can improve the design later if we need
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
…to addonTemplate
|
@seanbudd , I've removed py2exe and addressed your feedback, except for the yaml configuration. I'll wait for your clarifications. |
This pull request introduces significant improvements to the translation utilities for NVDA and its add-on template. The most important changes include a major refactor of the Crowdin integration logic in
l10nUtil.py, the removal of the now-redundantcrowdinSync.py, the addition of new dependency and build configuration inpyproject.toml, and enhancements to developer documentation and pre-commit configuration. These updates make the translation workflow more robust, flexible, and maintainable.Crowdin integration refactor and CLI improvements:
l10nUtil.pyfor uploading source files, specifying Crowdin project names/IDs, and improved flexibility for translation file operations. [1] [2] [3] [4] [5]source/crowdinSync.pyscript, consolidating all Crowdin-related logic intol10nUtil.py.Project configuration and dependency management:
pyproject.tomlto include project metadata, dependency management, build system configuration, and tool settings forruffandpyright. Added a CLI entry point forl10nutil..python-versionto specify Python 3.13.11 for better reproducibility..pre-commit-config.yamlwith improved argument handling and added a hook for verifying theuvlock file. [1] [2]Documentation:
readme.mdwith clear instructions for installing dependencies and building executables usinguvandpyinstaller.