+
Skip to content

Conversation

Prateekshit73
Copy link
Contributor

@Prateekshit73 Prateekshit73 commented Sep 6, 2025

Proposed change

Added spell checking functionality to pre-commit hooks and Makefile.
Resolves #2308.

Type of change

  • New country/market holidays support (thank you!)
  • Supported country/market holidays update (calendar discrepancy fix, localization)
  • Existing code/documentation/test/process quality improvement (best practice, cleanup, refactoring, optimization)
  • Dependency update (version deprecation/pin/upgrade)
  • Bugfix (non-breaking change which fixes an issue)
  • Breaking change (a code change causing existing functionality to break)
  • New feature (new holidays functionality in general)

Checklist

Copy link
Contributor

coderabbitai bot commented Sep 6, 2025

Summary by CodeRabbit

  • New Features

    • Added spell-checking to the default check workflow, covering code, docs, and localization files.
    • Cross-platform support via Docker-based and Windows scripts.
    • Automated sorting of a custom dictionary for consistent results.
  • Chores

    • Introduced a containerized spell-check toolchain and supporting configuration.
    • Expanded clean tasks to remove additional build and cache artifacts.
  • Documentation

    • Help/usage output now lists the spellcheck command.
  • Style

    • Minor formatting adjustments to pre-commit configuration (no behavioral changes).

Walkthrough

Adds cspell-based spellcheck infra: Docker image, npm manifest and dictionaries, cspell config and empty custom dictionary, Makefile and Windows wrappers to run spellcheck, a script to sort the custom dictionary, and a minor pre-commit formatting tweak. No production code changes.

Changes

Cohort / File(s) Summary
Pre-commit config formatting
\.pre-commit-config.yaml
Minor formatting/indentation and quote normalization only; no behavioral change.
Build orchestration (Unix + Windows)
Makefile
Makefile, make.cmd
Adds spellcheck target, .PHONY: spellcheck, sort-custom-dict target, integrates spellcheck into check, extends clean, updates help. Windows make.cmd adds :Sort-custom-dict and :Spellcheck, wires Call :Spellcheck into :Check.
cspell toolchain (config, Docker, wrappers, package, dict)
cspell/*
cspell/Dockerfile, cspell/Makefile, cspell/make.cmd, cspell/package.json, cspell/cspell.json, cspell/custom-dict.txt
New Dockerfile to run cspell, local cspell Makefile and Windows wrapper to build/run container, npm manifest with cspell + many dictionaries, cspell.json configuration, and a placeholder custom-dict.txt.
Utility script
tools/sort_cspell_dict.py
New script sort_custom_dict() that reads cspell/custom-dict.txt, deduplicates, sorts, and writes it back with a trailing newline.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Linked Issues Check ⚠️ Warning The changes partially satisfy issue #2308: the PR selects cspell and adds cspell configuration, a Docker image, a package.json with many dictionaries, Makefile targets, Windows helpers, and a sorting tool for a custom dictionary, which addresses tooling selection and multi-language support locally; however it does not actually add a cspell pre-commit hook (only formatting edits to .pre-commit-config.yaml), provides no CI workflow integration, and the custom dictionary file is empty, so the primary linked objectives (pre-commit and CI integration and a populated custom dictionary) remain unmet. To satisfy the linked-issue requirements, add and commit a cspell entry to .pre-commit-config.yaml, add a CI job (e.g., GitHub Actions) that runs make spellcheck or the cspell Docker target, populate cspell/custom-dict.txt with curated project terms or generate it from l10n sources, and document IDE/CI setup and install steps; update the PR once those items are implemented.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title is concise and accurately highlights the main repository change—adding spell-checking and Makefile integration; however it also claims pre-commit hook changes while the .pre-commit-config.yaml in the diff only shows formatting-level edits and no added spell-check hook, so the title is only partially accurate to the full changeset.
Out of Scope Changes Check ✅ Passed All added or modified files are focused on introducing cspell-based spell checking and supporting tooling (Makefile, cspell/*, tools script, Windows helpers); there are no unrelated codebase or API changes detected beyond reasonable maintenance tweaks to Makefile clean targets.
Description Check ✅ Passed The PR description is on-topic and directly related to the changeset, stating that spell-checking was added and linking the issue it intends to resolve, so it meets this lenient check.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 336879a and cc11806.

📒 Files selected for processing (1)
  • .pre-commit-config.yaml (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: PPsyrius
PR: vacanza/holidays#2608
File: holidays/locale/en_US/LC_MESSAGES/VC.po:76-76
Timestamp: 2025-06-10T05:08:07.939Z
Learning: For the holidays project, localization file formatting issues (like missing terminal periods in .po files) should be automatically fixed by running `make l10n` command (which is included in `make check`). Authors should be directed to use this automated tooling instead of manual formatting fixes.
🔇 Additional comments (2)
.pre-commit-config.yaml (2)

23-25: Formatting-only tweak to pyupgrade — OK.

No functional impact. Keep as-is.


64-64: Quote style change — OK; tox-ini-fmt rev is current (1.6.0).

Verified latest release is 1.6.0 (released July 30, 2025); no later releases or breaking changes since 1.6.0.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 27

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
make.cmd (1)

13-19: Fail fast on errors in :Check.

Right now, a later success can mask earlier failures (e.g., spellcheck failing but tests passing). Propagate ERRORLEVEL after each step.

Apply:

 :Check
-    Call :L10n
-    Call :Pre-commit
-    Call :Doc
-    Call :Spellcheck
-    Call :Test
-    Exit /B
+    Call :L10n        & If ErrorLevel 1 Exit /B %ERRORLEVEL%
+    Call :Pre-commit  & If ErrorLevel 1 Exit /B %ERRORLEVEL%
+    Call :Doc         & If ErrorLevel 1 Exit /B %ERRORLEVEL%
+    Call :Spellcheck  & If ErrorLevel 1 Exit /B %ERRORLEVEL%
+    Call :Test        & Exit /B %ERRORLEVEL%
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a94bcfa and 2420d52.

⛔ Files ignored due to path filters (1)
  • cspell/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (11)
  • .pre-commit-config.yaml (1 hunks)
  • Makefile (2 hunks)
  • cspell/Dockerfile (1 hunks)
  • cspell/Makefile (1 hunks)
  • cspell/cspell.json (1 hunks)
  • cspell/custom-dict.txt (1 hunks)
  • cspell/dictionaries/hindi/hi.txt (1 hunks)
  • cspell/dictionaries/hindi/package.json (1 hunks)
  • cspell/make.cmd (1 hunks)
  • cspell/package.json (1 hunks)
  • make.cmd (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: PPsyrius
PR: vacanza/holidays#2398
File: holidays/groups/islamic.py:301-301
Timestamp: 2025-04-01T14:14:01.519Z
Learning: Running `make pre-commit` in the holidays project can automatically fix common code style issues like whitespace in blank lines.
🪛 checkmake (0.2.2)
cspell/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)

Makefile

[warning] 3-3: Missing required phony target "all"

(minphony)


[warning] 3-3: Missing required phony target "clean"

(minphony)


[warning] 3-3: Missing required phony target "test"

(minphony)

🪛 Checkov (3.2.334)
cspell/Dockerfile

[LOW] 1-24: Ensure that HEALTHCHECK instructions have been added to container images

(CKV_DOCKER_2)

🔇 Additional comments (4)
cspell/custom-dict.txt (1)

1-33: Ensure CI invokes the sort-custom-dict pre-commit hook
The sort-custom-dict hook is already defined in .pre-commit-config.yaml and runs when you run make pre-commit (which calls pre-commit run --all-files). Confirm that your CI pipeline also runs this target (or pre-commit run --all-files) so cspell/custom-dict.txt stays consistently sorted and deduped.

Makefile (1)

14-14: Help text vs actual scope mismatch.

Help says “localization and documentation files” but the config scans broadly. Update help or cspell.json (see cspell.json comment).

.pre-commit-config.yaml (2)

78-81: Confirm whether case-insensitive dedupe is desired.

The current sort -f | uniq -i can drop intentionally cased entries (e.g., “US” vs “Us”). If casing matters for your custom dict, switch to case-sensitive dedupe.

-        entry: bash -c '... sort -f --stable | LC_ALL=C uniq -i >> ...'
+        entry: bash -c '... sort --stable | LC_ALL=C uniq >> ...'

75-75: Good: pinned cspell version.

Pinning cspell@8.19.4 ensures reproducibility across contributors.

hooks:
- id: cspell
name: cspell
entry: cspell --config ./cspell/cspell.json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Quiet, faster cspell runs.

Trim noise and speed up CI with caching and no-progress output.

-        entry: cspell --config ./cspell/cspell.json
+        entry: cspell --config ./cspell/cspell.json --no-progress --cache

Add .cspellcache to .gitignore if not already ignored.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
entry: cspell --config ./cspell/cspell.json
entry: cspell --config ./cspell/cspell.json --no-progress --cache
🤖 Prompt for AI Agents
In .pre-commit-config.yaml around line 72, the cspell pre-commit entry is noisy
and slow; update the entry to run cspell with quiet/no-progress and caching by
adding the flags --no-progress and --cache to the command (e.g. cspell --config
./cspell/cspell.json --no-progress --cache) so CI is faster and less verbose,
and add .cspellcache to .gitignore (if not already present) to avoid committing
the cache file.

- id: cspell
name: cspell
entry: cspell --config ./cspell/cspell.json
files: \.(py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml)$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Broaden file patterns (optional).

If you want spellcheck on scripts and build files too, include these.

-        files: \.(py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml)$
+        files: (^Dockerfile$|\.((py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml|sh|bash|bat|cmd|ps1|mk))$)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
files: \.(py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml)$
files: (^Dockerfile$|\.((py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml|sh|bash|bat|cmd|ps1|mk))$)
🤖 Prompt for AI Agents
In .pre-commit-config.yaml at line 73, the files regex only covers common
text/code extensions and omits scripts and build files; update the pattern to
also match shell and scripting extensions and common build filenames (e.g., add
\.(sh|bash|zsh|ps1|gradle|mk)$ and include literal filenames like ^Dockerfile$
and ^Makefile$ or their variants) so the spellcheck hook runs on scripts and
build files too; modify the files entry to combine the existing extensions with
these additional patterns (using alternation or a second hook entry) ensuring
YAML syntax and proper escaping.

files: \.(py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml)$
language: node
additional_dependencies: ["cspell@8.19.4"]
exclude: ^(docs/_build|node_modules|\.venv|__pycache__|dist|build|\.mypy_cache|\.pytest_cache|\.egg-info|\.tox|snapshots)/$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix exclude regex so directories are actually excluded.

The $ forces a full-string match and won’t exclude files inside those dirs. Use a prefix match that ends with a slash.

-        exclude: ^(docs/_build|node_modules|\.venv|__pycache__|dist|build|\.mypy_cache|\.pytest_cache|\.egg-info|\.tox|snapshots)/$
+        exclude: ^(docs/_build|node_modules|\.venv|__pycache__|dist|build|\.mypy_cache|\.pytest_cache|\.egg-info|\.tox|snapshots)/
🤖 Prompt for AI Agents
In .pre-commit-config.yaml around line 76, the exclude regex uses a trailing $
which matches only the exact directory path and therefore won't exclude files
inside those directories; change the pattern to use a prefix match that ends
with a slash (e.g. remove the trailing $ and ensure the directory list is
followed by /) so the regex excludes any path that begins with those directories
rather than only the directory name itself.

Comment on lines 78 to 81
name: sort and uniquify custom-dict.txt
entry: bash -c 'LC_ALL=C grep "^#" cspell/custom-dict.txt > cspell/custom-dict.txt.tmp && LC_ALL=C grep -v "^#" cspell/custom-dict.txt | grep -v "^[[:space:]]*$" | LC_ALL=C sort -f --stable | LC_ALL=C uniq -i >> cspell/custom-dict.txt.tmp && mv cspell/custom-dict.txt.tmp cspell/custom-dict.txt'
files: ^cspell/custom-dict\.txt$
language: system
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make the dict sorter cross‑platform (drop bash).

This hook will fail on Windows shells. Use a tiny Python hook instead.

-      - id: sort-custom-dict
-        name: sort and uniquify custom-dict.txt
-        entry: bash -c 'LC_ALL=C grep "^#" cspell/custom-dict.txt > cspell/custom-dict.txt.tmp && LC_ALL=C grep -v "^#" cspell/custom-dict.txt | grep -v "^[[:space:]]*$" | LC_ALL=C sort -f --stable | LC_ALL=C uniq -i >> cspell/custom-dict.txt.tmp && mv cspell/custom-dict.txt.tmp cspell/custom-dict.txt'
-        files: ^cspell/custom-dict\.txt$
-        language: system
+      - id: sort-custom-dict
+        name: sort and uniquify custom-dict.txt
+        entry: python tools/sort_cspell_dict.py
+        files: ^cspell/custom-dict\.txt$
+        language: python
+        pass_filenames: false

Add at tools/sort_cspell_dict.py:

#!/usr/bin/env python
from pathlib import Path

p = Path("cspell/custom-dict.txt")
comments, words = [], []
for line in p.read_text(encoding="utf-8").splitlines():
    if line.startswith("#"):
        comments.append(line)
    else:
        s = line.strip()
        if s:
            words.append(s)

# Case-sensitive sort+dedupe to preserve intentional casing
seen, out = set(), []
for w in sorted(words):
    if w not in seen:
        seen.add(w)
        out.append(w)

p.write_text("\n".join([*comments, *out]) + "\n", encoding="utf-8")
🤖 Prompt for AI Agents
In .pre-commit-config.yaml around lines 78 to 81, the current hook uses a bash
one-liner which will fail on Windows; replace it with a cross-platform tiny
Python script and call that from the hook. Add the script
tools/sort_cspell_dict.py (as described in the review) that reads
cspell/custom-dict.txt, preserves comment lines, strips/filters blank lines,
sorts and deduplicates words while preserving case, and rewrites the file with a
trailing newline; make the script executable and committed. Then update the hook
entry to invoke the script with the system language (e.g., entry: python3
tools/sort_cspell_dict.py or use {python} from pre-commit) and keep files:
^cspell/custom-dict\.txt$ so the hook runs cross-platform.

Comment on lines 21 to 23
:Spellcheck
call cspell\make.cmd cspell-check
Exit /B %ERRORLEVEL%
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Make the Spellcheck call path-safe.

Use script-dir anchored path to survive spaces/symlinks.

Apply:

 :Spellcheck
-    call cspell\make.cmd cspell-check
+    call "%~dp0cspell\make.cmd" cspell-check
     Exit /B %ERRORLEVEL%
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:Spellcheck
call cspell\make.cmd cspell-check
Exit /B %ERRORLEVEL%
:Spellcheck
call "%~dp0cspell\make.cmd" cspell-check
Exit /B %ERRORLEVEL%
🤖 Prompt for AI Agents
In make.cmd around lines 21 to 23, the call to cspell\make.cmd is not path-safe;
replace it with a script-dir anchored, quoted path using the batch %~dp0
variable (e.g. call "%~dp0cspell\make.cmd") so the command survives spaces and
symlinks, then keep the existing Exit /B %ERRORLEVEL% unchanged.

Comment on lines +1 to +4
-include cspell/Makefile

.PHONY: spellcheck

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Declare common phony targets (quiet checkmake).

- .PHONY: spellcheck
+.PHONY: all clean test spellcheck help doc l10n package pre-commit setup release-notes sbom snapshot tox check
🧰 Tools
🪛 checkmake (0.2.2)

[warning] 3-3: Missing required phony target "all"

(minphony)


[warning] 3-3: Missing required phony target "clean"

(minphony)


[warning] 3-3: Missing required phony target "test"

(minphony)

🤖 Prompt for AI Agents
In Makefile around lines 1 to 4, the .PHONY declaration only lists spellcheck;
expand it to declare common phony targets so checkmake and quiet (and other
frequently used phony targets) are recognized. Update the .PHONY line to include
spellcheck, checkmake, quiet and any other repository-standard phony targets
such as all, test, clean, etc., ensuring the Makefile consistently declares
every non-file-producing target as phony.

@Prateekshit73
Copy link
Contributor Author

It still reports 25,729 unknown words. Should I add custom dictionaries like I did for Hindi, or is there another recommended workaround?

@Prateekshit73 Prateekshit73 marked this pull request as draft September 7, 2025 03:56
"path": "custom-dict.txt"
},
{
"name": "hi",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not what we want. Try resolving it with existing dictionaries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have already included every available dictionary as a dependency. Here is the complete list for reference:
Natural Language Dictionaries

}
],
"dictionaries": [
"ar",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that all of them need to be installed as dependencies.

hooks:
- id: tox-ini-fmt

- repo: local
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it part of make check instead

Comment on lines +81 to +95
"node_modules/**",
".git/**",
".venv/**",
"__pycache__/**",
"*.pyc",
"dist/**",
"build/**",
".mypy_cache/**",
".pytest_cache/**",
"docs/_build/**",
"snapshots/**",
"*.egg-info/**",
".tox/**",
"requirements/*.txt",
"cspell/dictionaries/**"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need all of them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which of these do you consider unnecessary or redundant? Should I remove any specific ones?

@Prateekshit73 Prateekshit73 marked this pull request as ready for review September 12, 2025 04:23
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.pre-commit-config.yaml (1)

68-78: Spellcheck isn’t integrated into pre-commit (only pre-push).

Issue #2308 asks for pre-commit integration. Add a lightweight hook that runs your Make target (no filenames) at pre-commit so contributors get feedback before push.

Apply:

   - repo: local
     hooks:
       - id: tests
         always_run: true
         entry: make check
         language: system
         name: run `make check`
         pass_filenames: false
         stages:
           - pre-push
+      - id: spellcheck
+        name: cspell (docs + l10n)
+        entry: make -s spellcheck
+        language: system
+        pass_filenames: false
+        stages:
+          - pre-commit
Makefile (1)

32-37: Also clean cspell cache.

Keeps tree tidy.

 	@rm -rf .mypy_cache .pytest_cache dist .tox
+	@rm -f .cspellcache
♻️ Duplicate comments (7)
make.cmd (3)

21-23: Anchor Python path to script dir (Windows path safety).

Avoid failures when repo path contains spaces/symlinks.

 :Sort-custom-dict
-    python tools/sort_cspell_dict.py
+    call python "%~dp0tools\sort_cspell_dict.py"
     Exit /B

25-28: Quote and anchor cspell\make.cmd call.

Same path-safety fix.

 :Spellcheck
     call :Sort-custom-dict
-    call cspell\make.cmd cspell-check
+    call "%~dp0cspell\make.cmd" cspell-check
     Exit /B %ERRORLEVEL%

45-46: Help text mismatches scope.

cspell currently scans docs + l10n (per cspell.json), not “code”. Update help or expand cspell “files”.

-    Echo     spellcheck    run spell check across the repository (code, docs, l10n)
+    Echo     spellcheck    run spell check on documentation and localization files
cspell/cspell.json (1)

101-101: Remove overbroad “Capitalized Word Pair” ignore.

This hides real typos in titles (e.g., “Nwe Year”).

-    "\\b[A-Z][a-z]+\\s+[A-Z][a-z]+\\b",
+    // removed: too broad and hides legitimate typos
Makefile (1)

3-3: Declare all common PHONY targets.

Avoid checkmake warnings and accidental file/target collisions.

-.PHONY: spellcheck
+.PHONY: all clean test spellcheck help doc l10n package pre-commit setup release-notes sbom snapshot tox check sort-custom-dict
cspell/Makefile (1)

12-13: Missing prerequisite target ‘cspell-run’ breaks make.

cspell-check depends on cspell-run but it’s undefined → “No rule to make target…”.

 cspell-check: CMD=--no-progress -r /holidays
-cspell-check: cspell-install cspell-run
+cspell-check: cspell-install cspell-run
+
+# placeholder to satisfy dependency (extend later if needed)
+cspell-run:
+	@true
cspell/package.json (1)

1-12: Mark package private; make this a pure tooling package.

Prevents accidental publish, removes unused entry point, and puts tooling under devDependencies.

Apply:

 {
   "name": "cspell-check",
+  "private": true,
   "version": "1.0.0",
   "description": "Spell checking for holidays project",
-  "main": "index.js",
   "scripts": {
     "spellcheck": "cspell"
   },
-  "dependencies": {
+  "devDependencies": {
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2420d52 and 336879a.

⛔ Files ignored due to path filters (1)
  • cspell/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .pre-commit-config.yaml (2 hunks)
  • Makefile (2 hunks)
  • cspell/Makefile (1 hunks)
  • cspell/cspell.json (1 hunks)
  • cspell/custom-dict.txt (1 hunks)
  • cspell/make.cmd (1 hunks)
  • cspell/package.json (1 hunks)
  • make.cmd (2 hunks)
  • tools/sort_cspell_dict.py (1 hunks)
🧰 Additional context used
🪛 checkmake (0.2.2)
cspell/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)

Makefile

[warning] 3-3: Missing required phony target "all"

(minphony)


[warning] 3-3: Missing required phony target "clean"

(minphony)


[warning] 3-3: Missing required phony target "test"

(minphony)

🔇 Additional comments (3)
.pre-commit-config.yaml (2)

23-23: Indentation fix for pyupgrade looks good.

No functional concerns here.


64-64: Quoting tox-ini-fmt rev is fine.

Safe, no action needed.

cspell/Makefile (1)

3-10: Build step LGTM.

Context and flags are correct; honors FORCE.

Comment on lines +13 to +72
"dictionaries": [
"ar",
"bg-bg",
"bn",
"ca",
"companies",
"cs-cz",
"da-dk",
"de-at",
"de-ch",
"de-de",
"el",
"en_us",
"en-au",
"en-ca",
"en-common-misspellings",
"en-gb",
"eo",
"es-es",
"et-ee",
"eu",
"fa-ir",
"fi-fi",
"fr-fr",
"gd",
"gl-es",
"grc",
"he",
"hr-hr",
"hu-hu",
"hy",
"id-id",
"it-it",
"la",
"lt-lt",
"lv",
"makefile",
"markdown",
"mk",
"mn-mn",
"nb-no",
"nl-nl",
"pl-pl",
"pt-br",
"pt-pt",
"python",
"ro-ro",
"ru-ru",
"scientific-terms-gb",
"sk-sk",
"sl-si",
"sr-cyrl",
"sr-latn",
"sv",
"software-terms",
"tr-tr",
"uk-ua",
"vi-vn",
"custom-dict"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Right-size dictionary set to reduce noise.

Enabling dozens of dictionaries globally increases false positives/negatives. Consider limiting to locales you actually ship and adding others incrementally.

Would you like a PR-ready matrix that maps repo locales to the minimal cspell-dict set?

🤖 Prompt for AI Agents
In cspell/cspell.json around lines 13 to 72, the file enables a very large
global dictionary list that increases noise; trim this list to just the language
dictionaries your app actually ships plus shared dictionaries (e.g., keep en-us
or en-gb depending on product locale, and retain essential global lists like
software-terms, makefile, markdown, python, custom-dict), remove all other
locale-specific dictionaries, and document any removed locales in a comment so
contributors can add them back via a per-folder or per-package cspell.json
when/if those locales are introduced.

Comment on lines +74 to +79
"files": [
"docs/**/*",
"README.md",
"scripts/l10n/**/*",
"mkdocs.yml"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Scope vs. messaging mismatch.

You advertise “code, docs, l10n” in help, but config scopes only docs + l10n. Either expand “files” to include code/script patterns or adjust help.

Example expansion:

   "files": [
     "docs/**/*",
     "README.md",
-    "scripts/l10n/**/*",
-    "mkdocs.yml"
+    "scripts/l10n/**/*",
+    "mkdocs.yml",
+    "**/*.py",
+    "**/*.sh",
+    "**/*.cmd",
+    "**/*.bat",
+    "Dockerfile",
+    "Makefile"
   ],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"files": [
"docs/**/*",
"README.md",
"scripts/l10n/**/*",
"mkdocs.yml"
],
"files": [
"docs/**/*",
"README.md",
"scripts/l10n/**/*",
"mkdocs.yml",
"**/*.py",
"**/*.sh",
"**/*.cmd",
"**/*.bat",
"Dockerfile",
"Makefile"
],
🤖 Prompt for AI Agents
In cspell/cspell.json around lines 74-79, the cspell "files" array currently
lists only docs and l10n paths while the project help claims scopes "code, docs,
l10n"; update the config to match the advertised scopes by adding code/script
file patterns (for example add src/**/*, **/*.ts, **/*.js, scripts/**/* or other
repo-specific code paths) so cspell runs on code as well as docs and l10n —
alternatively, if you intend to exclude code, update the help text to remove
"code" from the advertised scopes; pick one approach and make the corresponding
change so help and config are consistent.

Comment on lines +81 to +96
"node_modules/**",
".git/**",
".venv/**",
"__pycache__/**",
"*.pyc",
"dist/**",
"build/**",
".mypy_cache/**",
".pytest_cache/**",
"docs/_build/**",
"snapshots/**",
"*.egg-info/**",
".tox/**",
"requirements/*.txt",
"cspell/dictionaries/**"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Ignore more noisy caches and tool dirs.

Reduce false positives and scan time.

   "ignorePaths": [
     "node_modules/**",
     ".git/**",
     ".venv/**",
+    ".direnv/**",
     "__pycache__/**",
     "*.pyc",
     "dist/**",
     "build/**",
     ".mypy_cache/**",
     ".pytest_cache/**",
+    ".ruff_cache/**",
+    ".github/**",
+    ".vscode/**",
+    ".idea/**",
     "docs/_build/**",
     "snapshots/**",
     "*.egg-info/**",
     ".tox/**",
     "requirements/*.txt",
+    "requirements/**/*.txt",
     "cspell/dictionaries/**"
   ],
🤖 Prompt for AI Agents
In cspell/cspell.json around lines 81 to 96, the ignore list is missing common
noisy caches and editor/tool directories which cause false positives and slower
scans; add entries such as ".vscode/**", ".idea/**", ".cache/**", "coverage/**",
"vendor/**", "target/**", ".terraform/**", ".gradle/**", ".bundle/**",
".sass-cache/**", ".DS_Store", ".history/**", ".parcel-cache/**", ".next/**",
"out/**" to the existing array so these directories and files are skipped by the
spellchecker; ensure patterns include /** where appropriate and keep the list
sorted/consistent with existing entries.

@@ -0,0 +1 @@
# Project-specific terms\n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove stray literal “\n” from header.

It should be a normal newline, not backslash+n in the file.

-# Project-specific terms\n
+# Project-specific terms
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Project-specific terms\n
# Project-specific terms
🤖 Prompt for AI Agents
In cspell/custom-dict.txt around lines 1 to 1, the header contains a literal
backslash+n sequence ("\\n") instead of an actual newline; remove the backslash
and ensure the line ends with a real newline character so the header reads "#
Project-specific terms" followed by a normal newline.

Comment on lines +37 to +42
:cspell-check
set CMD=--no-progress -r /holidays
call :cspell-install
call :cspell-run
docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
goto end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Propagate failures from install/run before docker run.

Ensure a failed build stops the pipeline.

 :cspell-check
 set CMD=--no-progress -r /holidays
 call :cspell-install
+if %errorlevel% neq 0 exit /b %errorlevel%
 call :cspell-run
+if %errorlevel% neq 0 exit /b %errorlevel%
 docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
 goto end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:cspell-check
set CMD=--no-progress -r /holidays
call :cspell-install
call :cspell-run
docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
goto end
:cspell-check
set CMD=--no-progress -r /holidays
call :cspell-install
if %errorlevel% neq 0 exit /b %errorlevel%
call :cspell-run
if %errorlevel% neq 0 exit /b %errorlevel%
docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
goto end
🤖 Prompt for AI Agents
In cspell/make.cmd around lines 37 to 42, the script currently always runs the
docker cspell lint step even if :cspell-install or :cspell-run failed; update
the script so failures propagate and stop the pipeline by checking the exit
status after each call and exiting early on non-zero. After calling
:cspell-install and :cspell-run, test ERRORLEVEL (or use CMD's || operator) and
if non-zero call exit /b %ERRORLEVEL% (or goto end with an error), so the docker
run is skipped when either prior step fails and the process returns the original
failure code.

Comment on lines +65 to +66
"cspell": "^8.19.4"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Align version pinning strategy with pre-commit.

Pre-commit often pins exact versions (e.g., cspell@8.19.4). Here you use a caret. Pick one strategy for both to avoid drift.

Run to compare versions:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
pre_commit_ver="$(rg -nP 'cspell@(\d+\.\d+\.\d+)' .pre-commit-config.yaml -or '$1' | head -n1 || true)"
pkg_ver="$(jq -r '.devDependencies.cspell // .dependencies.cspell' cspell/package.json | sed 's/^[^0-9]*//')"
echo "pre-commit cspell: ${pre_commit_ver:-<none>}"
echo "package.json cspell: ${pkg_ver:-<none>}"
test -n "${pre_commit_ver}" && test -n "${pkg_ver}" && [ "$pre_commit_ver" = "$pkg_ver" ] && echo "OK: versions match" || echo "MISMATCH: consider pinning consistently"

Length of output: 93


Align cspell version pinning between pre-commit and package.json

  • cspell/package.json (lines ~65–66) uses "^8.19.4"; .pre-commit-config.yaml contains no cspell pin (script: pre-commit cspell: ; package.json cspell: 8.19.4 → MISMATCH).
  • Action: either pin the exact version in package.json (remove caret) or add the same exact rev/version to .pre-commit-config.yaml so both use the same version.
🤖 Prompt for AI Agents
In cspell/package.json around lines 65–66 the cspell dependency is specified as
"^8.19.4", which mismatches the unpinned cspell usage in
.pre-commit-config.yaml; fix by making both use the identical exact version:
either remove the caret in cspell/package.json to pin "8.19.4" exactly, or
update .pre-commit-config.yaml to reference the same explicit cspell
revision/version (8.19.4); ensure both files are updated so they match exactly
and run a quick install or pre-commit check to verify consistency.

@echo " package build package distribution"
@echo " pre-commit run pre-commit against all files"
@echo " setup setup development environment"
@echo " spellcheck run spell check across the repository (code, docs, l10n)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Help text mismatches actual scope.

Mirror cspell.json (docs + l10n) or expand cspell “files.”

-	@echo "    spellcheck    run spell check across the repository (code, docs, l10n)"
+	@echo "    spellcheck    run spell check on documentation and localization files"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@echo " spellcheck run spell check across the repository (code, docs, l10n)"
@echo " spellcheck run spell check on documentation and localization files"
🤖 Prompt for AI Agents
In Makefile around line 14, the help text for the "spellcheck" target claims it
runs across "code, docs, l10n" but does not match cspell.json's actual "files"
configuration; update the Makefile help text to exactly mirror the glob list or
named scopes from cspell.json, or alternatively modify cspell.json to include
docs and l10n paths so the help text is correct—ensure the phrasing and scope in
the echo string precisely reflect the cspell "files" entries so users see
accurate help output.

Comment on lines +28 to +31
spellcheck: sort-custom-dict
@command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not found. Install Docker or skip spellcheck."; exit 127; }
$(MAKE) cspell-check

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Optional: enable caching to speed up repeated checks.

Mount cache via cspell/Makefile; ensure .cspellcache is ignored.

 spellcheck: sort-custom-dict
 	@command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not found. Install Docker or skip spellcheck."; exit 127; }
-	$(MAKE) cspell-check
+	$(MAKE) cspell-check CMD='--no-progress --cache --cache-location /holidays/.cspellcache -r /holidays'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
spellcheck: sort-custom-dict
@command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not found. Install Docker or skip spellcheck."; exit 127; }
$(MAKE) cspell-check
spellcheck: sort-custom-dict
@command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not found. Install Docker or skip spellcheck."; exit 127; }
$(MAKE) cspell-check CMD='--no-progress --cache --cache-location /holidays/.cspellcache -r /holidays'
🤖 Prompt for AI Agents
In Makefile around lines 28-31, the spellcheck target should be updated to
enable caching for faster repeated runs: modify the docker invocation used by
cspell-check to mount a host cache directory (and the .cspellcache file) into
the container as volumes (e.g., map a repo-local .cspellcache and a
.cache/cspell or similar path) so cspell can reuse results across runs, and
update repository ignores to include .cspellcache if not already ignored; ensure
the Makefile preserves the existing docker-not-found check and exits
appropriately when docker is missing.

Comment on lines +10 to +13
dict_file = Path(__file__).parent.parent / "cspell" / "custom-dict.txt"
if not dict_file.exists():
print(f"Dictionary file {dict_file} not found.")
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fail fast on missing dictionary.

Printing and returning hides errors in CI/Make. Exit non‑zero.

-    if not dict_file.exists():
-        print(f"Dictionary file {dict_file} not found.")
-        return
+    if not dict_file.exists():
+        print(f"Dictionary file {dict_file} not found.", file=sys.stderr)
+        sys.exit(1)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In tools/sort_cspell_dict.py around lines 10 to 13, the script currently prints
a message and returns when the dictionary file is missing which hides failures
in CI; replace the print + return with a non‑zero exit so the process fails fast
(e.g., import sys at top if not present and call sys.exit(1) with a helpful
message or raise SystemExit(1)); ensure the exit path returns a non‑zero status
so CI/Make detects the error.

Comment on lines +18 to +33
# Remove duplicates while preserving order (case-sensitive)
seen = set()
unique_words = []
for word in words:
if word not in seen:
seen.add(word)
unique_words.append(word)

# Sort the words
unique_words.sort()

with open(dict_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(unique_words) + '\n')

print(f"Sorted and uniquified {dict_file}")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Preserve comments, drop blanks, dedupe case‑insensitively, and sort only words.

Current logic sorts comments and keeps blanks, and dedupes case‑sensitively. This will scramble headers and allow near‑duplicates. Fix as below.

-    # Remove duplicates while preserving order (case-sensitive)
-    seen = set()
-    unique_words = []
-    for word in words:
-        if word not in seen:
-            seen.add(word)
-            unique_words.append(word)
-
-    # Sort the words
-    unique_words.sort()
-
-    with open(dict_file, 'w', encoding='utf-8') as f:
-        f.write('\n'.join(unique_words) + '\n')
-
-    print(f"Sorted and uniquified {dict_file}")
+    comments, raw_words = [], []
+    for line in words:
+        if line.startswith("#"):
+            comments.append(line.rstrip())
+        else:
+            s = line.strip()
+            if s:
+                raw_words.append(s)
+
+    # Case-insensitive dedupe, stable
+    seen_ci = set()
+    uniq_words = []
+    for w in raw_words:
+        k = w.lower()
+        if k not in seen_ci:
+            seen_ci.add(k)
+            uniq_words.append(w)
+
+    # Sort words case-insensitively; keep comments as-is on top
+    uniq_words.sort(key=str.lower)
+
+    with open(dict_file, 'w', encoding='utf-8') as f:
+        out = [*comments, *uniq_words]
+        f.write('\n'.join(out) + '\n')
+
+    print(f"Sorted and uniquified {dict_file}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Remove duplicates while preserving order (case-sensitive)
seen = set()
unique_words = []
for word in words:
if word not in seen:
seen.add(word)
unique_words.append(word)
# Sort the words
unique_words.sort()
with open(dict_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(unique_words) + '\n')
print(f"Sorted and uniquified {dict_file}")
comments, raw_words = [], []
for line in words:
if line.startswith("#"):
comments.append(line.rstrip())
else:
s = line.strip()
if s:
raw_words.append(s)
# Case-insensitive dedupe, stable
seen_ci = set()
uniq_words = []
for w in raw_words:
k = w.lower()
if k not in seen_ci:
seen_ci.add(k)
uniq_words.append(w)
# Sort words case-insensitively; keep comments as-is on top
uniq_words.sort(key=str.lower)
with open(dict_file, 'w', encoding='utf-8') as f:
out = [*comments, *uniq_words]
f.write('\n'.join(out) + '\n')
print(f"Sorted and uniquified {dict_file}")
🤖 Prompt for AI Agents
In tools/sort_cspell_dict.py around lines 18 to 33, the current code removes
duplicates case-sensitively, keeps blank lines and sorts comments too; change it
to: treat lines starting with '#' as comments and preserve their original order,
drop blank lines entirely, collect non-comment lines as words, dedupe words
case-insensitively while keeping the first-seen original casing, sort the
deduped words using a case-insensitive key, and when writing the file output
preserved comment lines first (in their original order), then a single blank
line (if there were comments) followed by the sorted unique words joined by '\n'
and a final '\n'.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.pre-commit-config.yaml (1)

68-78: Add a lightweight cspell hook at pre-commit (optional, faster feedback).

Right now cspell runs via make check on pre-push. Consider a dedicated pre-commit hook that scans only staged files with cache to reduce noise and catch issues earlier.

Proposed addition:

+  - repo: local
+    hooks:
+      - id: cspell
+        name: cspell (staged files)
+        entry: cspell --config ./cspell/cspell.json --no-progress --cache
+        language: system
+        pass_filenames: true
+        stages: [pre-commit]
+        files: '(^Dockerfile$|^Makefile$|\.((py|md|rst|txt|yml|yaml|po|ini|cfg|conf|env|toml|json|properties|xml|sh|bash|bat|cmd|ps1|mk))$)'
+        exclude: ^(docs/_build|node_modules|\.venv|\.direnv|__pycache__|dist|build|\.mypy_cache|\.pytest_cache|\.ruff_cache|\.egg-info|\.tox|snapshots|\.git|\.vscode|\.idea)/
♻️ Duplicate comments (6)
cspell/cspell.json (2)

101-101: Remove overbroad “Capitalized Word Pair” ignore; it hides real typos.

This regex suppresses many legitimate errors (e.g., “Nwe Year”). It was previously flagged; looks reintroduced.

Apply:

-    "\\b[A-Z][a-z]+\\s+[A-Z][a-z]+\\b",
+    // Removed: too broad and hides real typos in titles.

97-105: Tighten ignore patterns for PO placeholders (optional).

Add patterns for gettext-style placeholders to cut noise.

Apply:

   "ignoreRegExpList": [
     "#\\w+",
     "<@\\w+>",
     "\\b[A-Z]{2,}\\b",
-    "\\b[A-Z][a-z]+\\s+[A-Z][a-z]+\\b",
     "\\b\\d+\\b",
     "\\b[A-Za-z]+_[A-Za-z]+\\b",
-    "\\bhttps?:\\/\\/[^\\s]+\\b"
+    "\\bhttps?:\\/\\/[^\\s]+\\b",
+    "%\\([A-Za-z_][A-Za-z0-9_]*\\)s",   // gettext named placeholders
+    "%[sd]%",                           // stray percent tokens
+    "%[sd]"                             // printf-style placeholders
   ],
Makefile (1)

3-3: Declare all phony targets (silence checkmake; clearer UX).

Apply:

-.PHONY: spellcheck
+.PHONY: all clean test spellcheck help doc l10n package pre-commit setup release-notes sbom snapshot tox check sort-custom-dict
make.cmd (1)

21-28: Make Windows calls path-safe and robust.

Apply:

:Sort-custom-dict
-    python tools/sort_cspell_dict.py
+    python "%~dp0tools\sort_cspell_dict.py"
     Exit /B

:Spellcheck
     call :Sort-custom-dict
-    call cspell\make.cmd cspell-check
+    call "%~dp0cspell\make.cmd" cspell-check
     Exit /B %ERRORLEVEL%
cspell/Makefile (1)

11-17: Missing cspell-run target breaks dependency chain.

Add a no-op target or drop it from prerequisites.

-cspell-check: cspell-install cspell-run
+cspell-check: cspell-install cspell-run
+
+cspell-run:
+	@true

Alternatively:

-cspell-check: cspell-install cspell-run
+cspell-check: cspell-install
cspell/package.json (1)

1-7: Mark package as private and drop unnecessary "main".

This is a tooling-only package; avoid accidental publish and remove unused entry point.

Apply:

   "version": "1.0.0",
   "description": "Spell checking for holidays project",
-  "main": "index.js",
+  "private": true,
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2420d52 and 336879a.

⛔ Files ignored due to path filters (1)
  • cspell/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .pre-commit-config.yaml (2 hunks)
  • Makefile (2 hunks)
  • cspell/Makefile (1 hunks)
  • cspell/cspell.json (1 hunks)
  • cspell/custom-dict.txt (1 hunks)
  • cspell/make.cmd (1 hunks)
  • cspell/package.json (1 hunks)
  • make.cmd (2 hunks)
  • tools/sort_cspell_dict.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: PPsyrius
PR: vacanza/holidays#2608
File: holidays/locale/en_US/LC_MESSAGES/VC.po:76-76
Timestamp: 2025-06-10T05:08:07.939Z
Learning: For the holidays project, localization file formatting issues (like missing terminal periods in .po files) should be automatically fixed by running `make l10n` command (which is included in `make check`). Authors should be directed to use this automated tooling instead of manual formatting fixes.
🪛 checkmake (0.2.2)
cspell/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)

Makefile

[warning] 3-3: Missing required phony target "all"

(minphony)


[warning] 3-3: Missing required phony target "clean"

(minphony)


[warning] 3-3: Missing required phony target "test"

(minphony)

🔇 Additional comments (9)
.pre-commit-config.yaml (2)

23-23: Formatting-only change — OK.


64-64: Formatting-only change — OK.

Makefile (1)

25-31: Good: docker presence guard and read-only bind via cspell sub-make.

make.cmd (1)

42-54: Help text matches behavior — nice.

cspell/Makefile (3)

3-9: Docker build context correctly set to cspell/ — good.


14-17: Good: read-only bind and explicit lint subcommand.


19-21: sort-custom-dict wired — verified.
Ran tools/sort_cspell_dict.py; it reported "Sorted and uniquified /home/jailuser/git/cspell/custom-dict.txt" and there were no diffs to cspell/custom-dict.txt — header comments remain on top.

cspell/package.json (2)

1-67: No action needed — lockfile present and Docker uses npm ci.

cspell/package-lock.json is committed and cspell/Dockerfile runs npm ci --ignore-scripts --no-audit --no-fund (and copies package-lock.json), so reproducible installs are already configured.


9-66: Move all cspell tooling to devDependencies.

Tooling (cspell + @cspell/* dictionaries) is dev-only — keep production installs clean. cspell/Dockerfile runs npm ci (no omit flags); verify CI/workflows/other Dockerfiles do not install with --omit=dev / --only=prod or NODE_ENV=production.

Apply:

-  "dependencies": {
+  "devDependencies": {
     "@cspell/dict-ar": "^1.1.6",
     "@cspell/dict-bg-bg": "^3.0.8",
     "@cspell/dict-bn": "^1.0.3",
     "@cspell/dict-ca": "^3.1.2",
     "@cspell/dict-companies": "^3.2.5",
     "@cspell/dict-cs-cz": "^3.0.8",
     "@cspell/dict-da-dk": "^4.1.2",
     "@cspell/dict-de-at": "^1.2.2",
     "@cspell/dict-de-ch": "^1.3.2",
     "@cspell/dict-de-de": "^4.1.2",
     "@cspell/dict-el": "^3.1.8",
     "@cspell/dict-en-au": "^1.1.7",
     "@cspell/dict-en-ca": "^1.0.45",
     "@cspell/dict-en-common-misspellings": "^2.1.6",
     "@cspell/dict-en-gb": "^5.0.14",
     "@cspell/dict-en_us": "^4.4.19",
     "@cspell/dict-eo": "^3.0.7",
     "@cspell/dict-es-es": "^3.0.8",
     "@cspell/dict-et-ee": "^3.1.6",
     "@cspell/dict-eu": "^1.0.6",
     "@cspell/dict-fa-ir": "^4.0.5",
     "@cspell/dict-fi-fi": "^1.1.3",
     "@cspell/dict-fr-fr": "^2.3.2",
     "@cspell/dict-gd": "^1.0.3",
     "@cspell/dict-gl-es": "^1.1.3",
     "@cspell/dict-grc": "^1.0.7",
     "@cspell/dict-he": "^4.0.5",
     "@cspell/dict-hr-hr": "^3.1.2",
     "@cspell/dict-hu-hu": "^1.1.2",
     "@cspell/dict-hy": "^1.0.3",
     "@cspell/dict-id-id": "^1.0.7",
     "@cspell/dict-it-it": "^3.1.6",
     "@cspell/dict-la": "^1.1.2",
     "@cspell/dict-lt-lt": "^4.0.6",
     "@cspell/dict-lv": "^1.1.6",
     "@cspell/dict-makefile": "^1.0.5",
     "@cspell/dict-markdown": "^2.0.12",
     "@cspell/dict-mk": "^1.0.3",
     "@cspell/dict-mn-mn": "^1.2.2",
     "@cspell/dict-nb-no": "^2.0.6",
     "@cspell/dict-nl-nl": "^2.4.2",
     "@cspell/dict-pt-br": "^2.4.2",
     "@cspell/dict-pt-pt": "^3.0.6",
     "@cspell/dict-python": "^4.2.19",
     "@cspell/dict-ro-ro": "^2.0.6",
     "@cspell/dict-scientific-terms-gb": "^1.0.6",
     "@cspell/dict-sk-sk": "^1.1.7",
     "@cspell/dict-sl-si": "^1.0.11",
     "@cspell/dict-software-terms": "^5.1.8",
     "@cspell/dict-sr-cyrl": "^1.1.6",
     "@cspell/dict-sr-latn": "^1.0.8",
     "@cspell/dict-sv": "^2.3.2",
     "@cspell/dict-tr-tr": "^3.0.6",
     "@cspell/dict-uk-ua": "^4.0.6",
     "@cspell/dict-vi-vn": "^3.0.6",
     "cspell": "^8.19.4"
   }

Comment on lines +12 to +72
],
"dictionaries": [
"ar",
"bg-bg",
"bn",
"ca",
"companies",
"cs-cz",
"da-dk",
"de-at",
"de-ch",
"de-de",
"el",
"en_us",
"en-au",
"en-ca",
"en-common-misspellings",
"en-gb",
"eo",
"es-es",
"et-ee",
"eu",
"fa-ir",
"fi-fi",
"fr-fr",
"gd",
"gl-es",
"grc",
"he",
"hr-hr",
"hu-hu",
"hy",
"id-id",
"it-it",
"la",
"lt-lt",
"lv",
"makefile",
"markdown",
"mk",
"mn-mn",
"nb-no",
"nl-nl",
"pl-pl",
"pt-br",
"pt-pt",
"python",
"ro-ro",
"ru-ru",
"scientific-terms-gb",
"sk-sk",
"sl-si",
"sr-cyrl",
"sr-latn",
"sv",
"software-terms",
"tr-tr",
"uk-ua",
"vi-vn",
"custom-dict"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

🛠️ Refactor suggestion

Reduce 25k+ unknowns with per-locale overrides and compounds.

Map locale folders to matching dictionaries and allow compounds for languages that need it (e.g., de, sv). This dramatically lowers false positives without bloating custom-dict.

Apply:

   ],
+  "overrides": [
+    { "filename": "holidays/locale/de_DE/LC_MESSAGES/*.po", "dictionaries": ["de-de"], "allowCompoundWords": true },
+    { "filename": "holidays/locale/de_AT/LC_MESSAGES/*.po", "dictionaries": ["de-at"], "allowCompoundWords": true },
+    { "filename": "holidays/locale/de_CH/LC_MESSAGES/*.po", "dictionaries": ["de-ch"], "allowCompoundWords": true },
+    { "filename": "holidays/locale/fr_FR/LC_MESSAGES/*.po", "dictionaries": ["fr-fr"] },
+    { "filename": "holidays/locale/es_ES/LC_MESSAGES/*.po", "dictionaries": ["es-es"] },
+    { "filename": "holidays/locale/pt_PT/LC_MESSAGES/*.po", "dictionaries": ["pt-pt"] },
+    { "filename": "holidays/locale/pt_BR/LC_MESSAGES/*.po", "dictionaries": ["pt-br"] },
+    { "filename": "holidays/locale/it_IT/LC_MESSAGES/*.po", "dictionaries": ["it-it"] },
+    { "filename": "holidays/locale/nl_NL/LC_MESSAGES/*.po", "dictionaries": ["nl-nl"] },
+    { "filename": "holidays/locale/sv_SE/LC_MESSAGES/*.po", "dictionaries": ["sv"], "allowCompoundWords": true },
+    { "filename": "holidays/locale/nb_NO/LC_MESSAGES/*.po", "dictionaries": ["nb-no"] },
+    { "filename": "holidays/locale/fi_FI/LC_MESSAGES/*.po", "dictionaries": ["fi-fi"] },
+    { "filename": "holidays/locale/pl_PL/LC_MESSAGES/*.po", "dictionaries": ["pl-pl"] },
+    { "filename": "holidays/locale/cs_CZ/LC_MESSAGES/*.po", "dictionaries": ["cs-cz"] },
+    { "filename": "holidays/locale/sk_SK/LC_MESSAGES/*.po", "dictionaries": ["sk-sk"] },
+    { "filename": "holidays/locale/sl_SI/LC_MESSAGES/*.po", "dictionaries": ["sl-si"] },
+    { "filename": "holidays/locale/ro_RO/LC_MESSAGES/*.po", "dictionaries": ["ro-ro"] },
+    { "filename": "holidays/locale/hu_HU/LC_MESSAGES/*.po", "dictionaries": ["hu-hu"] },
+    { "filename": "holidays/locale/ru_RU/LC_MESSAGES/*.po", "dictionaries": ["ru-ru"] },
+    { "filename": "holidays/locale/uk_UA/LC_MESSAGES/*.po", "dictionaries": ["uk-ua"] },
+    { "filename": "holidays/locale/tr_TR/LC_MESSAGES/*.po", "dictionaries": ["tr-tr"] },
+    { "filename": "holidays/locale/el_GR/LC_MESSAGES/*.po", "dictionaries": ["el"] },
+    { "filename": "holidays/locale/he_IL/LC_MESSAGES/*.po", "dictionaries": ["he"] },
+    { "filename": "holidays/locale/ar_*/LC_MESSAGES/*.po", "dictionaries": ["ar"] },
+    { "filename": "holidays/locale/hi_IN/LC_MESSAGES/*.po", "dictionaries": ["hi"] },
+    { "filename": "holidays/locale/id_ID/LC_MESSAGES/*.po", "dictionaries": ["id-id"] },
+    { "filename": "holidays/locale/vi_VN/LC_MESSAGES/*.po", "dictionaries": ["vi-vn"] },
+    { "filename": "holidays/locale/ga_IE/LC_MESSAGES/*.po", "dictionaries": ["gd"] },
+    { "filename": "holidays/locale/la_LA/LC_MESSAGES/*.po", "dictionaries": ["la"] }
+  ],

If helpful, I can generate the full overrides list based on the actual locales present.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
],
"dictionaries": [
"ar",
"bg-bg",
"bn",
"ca",
"companies",
"cs-cz",
"da-dk",
"de-at",
"de-ch",
"de-de",
"el",
"en_us",
"en-au",
"en-ca",
"en-common-misspellings",
"en-gb",
"eo",
"es-es",
"et-ee",
"eu",
"fa-ir",
"fi-fi",
"fr-fr",
"gd",
"gl-es",
"grc",
"he",
"hr-hr",
"hu-hu",
"hy",
"id-id",
"it-it",
"la",
"lt-lt",
"lv",
"makefile",
"markdown",
"mk",
"mn-mn",
"nb-no",
"nl-nl",
"pl-pl",
"pt-br",
"pt-pt",
"python",
"ro-ro",
"ru-ru",
"scientific-terms-gb",
"sk-sk",
"sl-si",
"sr-cyrl",
"sr-latn",
"sv",
"software-terms",
"tr-tr",
"uk-ua",
"vi-vn",
"custom-dict"
],
],
"dictionaries": [
"ar",
"bg-bg",
"bn",
"ca",
"companies",
"cs-cz",
"da-dk",
"de-at",
"de-ch",
"de-de",
"el",
"en_us",
"en-au",
"en-ca",
"en-common-misspellings",
"en-gb",
"eo",
"es-es",
"et-ee",
"eu",
"fa-ir",
"fi-fi",
"fr-fr",
"gd",
"gl-es",
"grc",
"he",
"hr-hr",
"hu-hu",
"hy",
"id-id",
"it-it",
"la",
"lt-lt",
"lv",
"makefile",
"markdown",
"mk",
"mn-mn",
"nb-no",
"nl-nl",
"pl-pl",
"pt-br",
"pt-pt",
"python",
"ro-ro",
"ru-ru",
"scientific-terms-gb",
"sk-sk",
"sl-si",
"sr-cyrl",
"sr-latn",
"sv",
"software-terms",
"tr-tr",
"uk-ua",
"vi-vn",
"custom-dict"
],
"overrides": [
{ "filename": "holidays/locale/de_DE/LC_MESSAGES/*.po", "dictionaries": ["de-de"], "allowCompoundWords": true },
{ "filename": "holidays/locale/de_AT/LC_MESSAGES/*.po", "dictionaries": ["de-at"], "allowCompoundWords": true },
{ "filename": "holidays/locale/de_CH/LC_MESSAGES/*.po", "dictionaries": ["de-ch"], "allowCompoundWords": true },
{ "filename": "holidays/locale/fr_FR/LC_MESSAGES/*.po", "dictionaries": ["fr-fr"] },
{ "filename": "holidays/locale/es_ES/LC_MESSAGES/*.po", "dictionaries": ["es-es"] },
{ "filename": "holidays/locale/pt_PT/LC_MESSAGES/*.po", "dictionaries": ["pt-pt"] },
{ "filename": "holidays/locale/pt_BR/LC_MESSAGES/*.po", "dictionaries": ["pt-br"] },
{ "filename": "holidays/locale/it_IT/LC_MESSAGES/*.po", "dictionaries": ["it-it"] },
{ "filename": "holidays/locale/nl_NL/LC_MESSAGES/*.po", "dictionaries": ["nl-nl"] },
{ "filename": "holidays/locale/sv_SE/LC_MESSAGES/*.po", "dictionaries": ["sv"], "allowCompoundWords": true },
{ "filename": "holidays/locale/nb_NO/LC_MESSAGES/*.po", "dictionaries": ["nb-no"] },
{ "filename": "holidays/locale/fi_FI/LC_MESSAGES/*.po", "dictionaries": ["fi-fi"] },
{ "filename": "holidays/locale/pl_PL/LC_MESSAGES/*.po", "dictionaries": ["pl-pl"] },
{ "filename": "holidays/locale/cs_CZ/LC_MESSAGES/*.po", "dictionaries": ["cs-cz"] },
{ "filename": "holidays/locale/sk_SK/LC_MESSAGES/*.po", "dictionaries": ["sk-sk"] },
{ "filename": "holidays/locale/sl_SI/LC_MESSAGES/*.po", "dictionaries": ["sl-si"] },
{ "filename": "holidays/locale/ro_RO/LC_MESSAGES/*.po", "dictionaries": ["ro-ro"] },
{ "filename": "holidays/locale/hu_HU/LC_MESSAGES/*.po", "dictionaries": ["hu-hu"] },
{ "filename": "holidays/locale/ru_RU/LC_MESSAGES/*.po", "dictionaries": ["ru-ru"] },
{ "filename": "holidays/locale/uk_UA/LC_MESSAGES/*.po", "dictionaries": ["uk-ua"] },
{ "filename": "holidays/locale/tr_TR/LC_MESSAGES/*.po", "dictionaries": ["tr-tr"] },
{ "filename": "holidays/locale/el_GR/LC_MESSAGES/*.po", "dictionaries": ["el"] },
{ "filename": "holidays/locale/he_IL/LC_MESSAGES/*.po", "dictionaries": ["he"] },
{ "filename": "holidays/locale/ar_*/LC_MESSAGES/*.po", "dictionaries": ["ar"] },
{ "filename": "holidays/locale/hi_IN/LC_MESSAGES/*.po", "dictionaries": ["hi"] },
{ "filename": "holidays/locale/id_ID/LC_MESSAGES/*.po", "dictionaries": ["id-id"] },
{ "filename": "holidays/locale/vi_VN/LC_MESSAGES/*.po", "dictionaries": ["vi-vn"] },
{ "filename": "holidays/locale/ga_IE/LC_MESSAGES/*.po", "dictionaries": ["gd"] },
{ "filename": "holidays/locale/la_LA/LC_MESSAGES/*.po", "dictionaries": ["la"] }
],
🤖 Prompt for AI Agents
In cspell/cspell.json around lines 12 to 72, the project-wide dictionary list is
too broad and creates 25k+ unknowns; add per-locale overrides that map each repo
locale folder (e.g., locales/de, locales/sv, etc.) to the matching
locale-specific dictionary (de-de, sv, etc.) and enable "allowCompoundWords":
true for compound-heavy languages (e.g., de-de, sv) so their valid compounds
aren’t flagged; update the "overrides" array with globs for each locale
directory pointing to the corresponding dictionary and set "dictionaries" and
"allowCompoundWords" as needed for those overrides, keeping custom-dict minimal.

Comment on lines +74 to +79
"files": [
"docs/**/*",
"README.md",
"scripts/l10n/**/*",
"mkdocs.yml"
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Include .po files to meet the “l10n coverage” objective (scoped).

Currently only docs and scripts are scanned; locale .po files aren’t. Add targeted globs for PO files.

Apply:

   "files": [
     "docs/**/*",
     "README.md",
-    "scripts/l10n/**/*",
-    "mkdocs.yml"
+    "scripts/l10n/**/*",
+    "mkdocs.yml",
+    "holidays/**/LC_MESSAGES/*.po"
   ],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"files": [
"docs/**/*",
"README.md",
"scripts/l10n/**/*",
"mkdocs.yml"
],
"files": [
"docs/**/*",
"README.md",
"scripts/l10n/**/*",
"mkdocs.yml",
"holidays/**/LC_MESSAGES/*.po"
],
🤖 Prompt for AI Agents
In cspell/cspell.json around lines 74 to 79, the "files" array doesn’t include
locale .po files so the l10n coverage objective isn't met; update the array to
add targeted globs that include PO files used by the project (for example add
entries matching common locations such as locale/**/*.po, po/**/*.po, and
i18n/**/*.po) so spellcheck scans translation files while keeping existing
doc/script globs.

@@ -0,0 +1 @@
# Project-specific terms\n
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix literal "\n" in file content; keep a real newline instead.

The line appears to contain the characters backslash + n. That will be treated as part of the word/comment. Replace with a normal newline and keep the file ending with a single trailing newline.

Apply:

-# Project-specific terms\n
+# Project-specific terms
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Project-specific terms\n
# Project-specific terms
🤖 Prompt for AI Agents
In cspell/custom-dict.txt around lines 1 to 1, the file contains the literal
backslash-n characters ("\\n") instead of an actual newline; remove the
characters "\\n" and replace them with a real newline character so the comment
reads "# Project-specific terms" on its own line, and ensure the file ends with
a single trailing newline (no extra blank lines or literal escape sequences).

🧹 Nitpick (assertive)

Answer to “25,729 unknown words” (strategy).

  • Scan PO files by locale with overrides (see cspell.json comment).
  • Prefer dictionaries over whitelisting; keep custom-dict lean.
  • Enable compounds for Germanic languages in overrides.
  • Add placeholder/format regexes for PO files.

I can script generation of overrides from holidays/locale/* directories. Want me to add that as tools/gen_cspell_overrides.py and wire it into make l10n?

🤖 Prompt for AI Agents
In cspell/custom-dict.txt around lines 1 to 1, the reviewer suggests automating
generation of cspell overrides and improving configuration: add a new script
tools/gen_cspell_overrides.py that scans holidays/locale/* (and other locale
dirs) to produce cspell.json overrides (enabling compounds for Germanic locales
and adding placeholder/format regex entries for PO strings), keep
custom-dict.txt minimal by preferring language dictionaries over whitelisting,
and update the Makefile l10n target to run this script before running cspell;
implement the script to emit valid JSON overrides, wire it into make l10n, and
ensure tests/CI use the generated overrides.

Comment on lines +18 to +27
:cspell-install
where docker >nul 2>nul
if %errorlevel% neq 0 (
echo ERROR: docker not found in PATH. Install Docker Desktop or add docker.exe to PATH.
goto end
)
set "build_args="
if defined FORCE set "build_args=--no-cache"
set "DOCKER_BUILDKIT=true" && docker build %build_args% -f cspell/Dockerfile -t cspell cspell
goto end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Docker check and build flow look good; minor nit: quote build context.

Apply:

-set "DOCKER_BUILDKIT=true" && docker build %build_args% -f cspell/Dockerfile -t cspell cspell
+set "DOCKER_BUILDKIT=true" && docker build %build_args% -f cspell/Dockerfile -t cspell "cspell"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:cspell-install
where docker >nul 2>nul
if %errorlevel% neq 0 (
echo ERROR: docker not found in PATH. Install Docker Desktop or add docker.exe to PATH.
goto end
)
set "build_args="
if defined FORCE set "build_args=--no-cache"
set "DOCKER_BUILDKIT=true" && docker build %build_args% -f cspell/Dockerfile -t cspell cspell
goto end
:cspell-install
where docker >nul 2>nul
if %errorlevel% neq 0 (
echo ERROR: docker not found in PATH. Install Docker Desktop or add docker.exe to PATH.
goto end
)
set "build_args="
if defined FORCE set "build_args=--no-cache"
set "DOCKER_BUILDKIT=true" && docker build %build_args% -f cspell/Dockerfile -t cspell "cspell"
goto end
🤖 Prompt for AI Agents
In cspell/make.cmd around lines 18 to 27, the docker build command passes the
build context unquoted which can break when the path contains spaces; update the
command to quote the build context (e.g., change the trailing cspell to
"cspell") so the context is treated as a single argument; keep the rest of the
line intact and ensure the quoted context is used with the existing build args
and options.

Comment on lines +37 to +42
:cspell-check
set CMD=--no-progress -r /holidays
call :cspell-install
call :cspell-run
docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
goto end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Read-only bind is good; also quote config path (Windows-safe).

Apply:

-docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
+docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c "cspell/cspell.json" %CMD%
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:cspell-check
set CMD=--no-progress -r /holidays
call :cspell-install
call :cspell-run
docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c cspell/cspell.json %CMD%
goto end
:cspell-check
set CMD=--no-progress -r /holidays
call :cspell-install
call :cspell-run
docker run --mount type=bind,src="%CD%",dst=/holidays,readonly --rm cspell lint -c "cspell/cspell.json" %CMD%
goto end
🤖 Prompt for AI Agents
In cspell/make.cmd around lines 37 to 42, keep the read-only bind mount but make
the cspell config path Windows-safe by quoting the -c argument; update the
docker run command to pass -c "cspell/cspell.json" (retain the existing --mount
... readonly and other flags) so the config path is treated as a single token on
Windows shells.

Comment on lines +10 to +65
"@cspell/dict-ar": "^1.1.6",
"@cspell/dict-bg-bg": "^3.0.8",
"@cspell/dict-bn": "^1.0.3",
"@cspell/dict-ca": "^3.1.2",
"@cspell/dict-companies": "^3.2.5",
"@cspell/dict-cs-cz": "^3.0.8",
"@cspell/dict-da-dk": "^4.1.2",
"@cspell/dict-de-at": "^1.2.2",
"@cspell/dict-de-ch": "^1.3.2",
"@cspell/dict-de-de": "^4.1.2",
"@cspell/dict-el": "^3.1.8",
"@cspell/dict-en-au": "^1.1.7",
"@cspell/dict-en-ca": "^1.0.45",
"@cspell/dict-en-common-misspellings": "^2.1.6",
"@cspell/dict-en-gb": "^5.0.14",
"@cspell/dict-en_us": "^4.4.19",
"@cspell/dict-eo": "^3.0.7",
"@cspell/dict-es-es": "^3.0.8",
"@cspell/dict-et-ee": "^3.1.6",
"@cspell/dict-eu": "^1.0.6",
"@cspell/dict-fa-ir": "^4.0.5",
"@cspell/dict-fi-fi": "^1.1.3",
"@cspell/dict-fr-fr": "^2.3.2",
"@cspell/dict-gd": "^1.0.3",
"@cspell/dict-gl-es": "^1.1.3",
"@cspell/dict-grc": "^1.0.7",
"@cspell/dict-he": "^4.0.5",
"@cspell/dict-hr-hr": "^3.1.2",
"@cspell/dict-hu-hu": "^1.1.2",
"@cspell/dict-hy": "^1.0.3",
"@cspell/dict-id-id": "^1.0.7",
"@cspell/dict-it-it": "^3.1.6",
"@cspell/dict-la": "^1.1.2",
"@cspell/dict-lt-lt": "^4.0.6",
"@cspell/dict-lv": "^1.1.6",
"@cspell/dict-makefile": "^1.0.5",
"@cspell/dict-markdown": "^2.0.12",
"@cspell/dict-mk": "^1.0.3",
"@cspell/dict-mn-mn": "^1.2.2",
"@cspell/dict-nb-no": "^2.0.6",
"@cspell/dict-nl-nl": "^2.4.2",
"@cspell/dict-pt-br": "^2.4.2",
"@cspell/dict-pt-pt": "^3.0.6",
"@cspell/dict-python": "^4.2.19",
"@cspell/dict-ro-ro": "^2.0.6",
"@cspell/dict-scientific-terms-gb": "^1.0.6",
"@cspell/dict-sk-sk": "^1.1.7",
"@cspell/dict-sl-si": "^1.0.11",
"@cspell/dict-software-terms": "^5.1.8",
"@cspell/dict-sr-cyrl": "^1.1.6",
"@cspell/dict-sr-latn": "^1.0.8",
"@cspell/dict-sv": "^2.3.2",
"@cspell/dict-tr-tr": "^3.0.6",
"@cspell/dict-uk-ua": "^4.0.6",
"@cspell/dict-vi-vn": "^3.0.6",
"cspell": "^8.19.4"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Scope dictionaries per path to cut false positives and speed up.

Load only the relevant language dictionaries for each l10n directory via cspell.json languageSettings (e.g., map holidays/locale/pt*/ to pt-pt/pt-br dicts, etc.) instead of enabling all dicts globally.

Comment on lines 18 to 24
check:
make l10n
make pre-commit
make doc
make spellcheck
make test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Confirm cspell/Makefile presence before delegating (optional).

If cspell/Makefile is missing, “make spellcheck” will fail. Guard with a check to degrade gracefully.

Apply:

 check:
 	make l10n
 	make pre-commit
 	make doc
-	make spellcheck
+	@if [ -f cspell/Makefile ]; then make spellcheck; else echo "spellcheck skipped (cspell/Makefile missing)"; fi
 	make test
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
check:
make l10n
make pre-commit
make doc
make spellcheck
make test
check:
make l10n
make pre-commit
make doc
@if [ -f cspell/Makefile ]; then make spellcheck; else echo "spellcheck skipped (cspell/Makefile missing)"; fi
make test
🤖 Prompt for AI Agents
In Makefile around lines 18 to 24, the check target unconditionally runs "make
spellcheck" which fails if cspell/Makefile is missing; modify the check target
to first verify cspell/Makefile exists and only invoke the spellcheck target
when present, otherwise print a clear message and continue (e.g., test for the
file path with a shell conditional and run make spellcheck on success, or echo a
skipping-warning on failure) so the target degrades gracefully.

Comment on lines +9 to +33
def sort_custom_dict():
dict_file = Path(__file__).parent.parent / "cspell" / "custom-dict.txt"
if not dict_file.exists():
print(f"Dictionary file {dict_file} not found.")
return

with open(dict_file, 'r', encoding='utf-8') as f:
words = f.read().splitlines()

# Remove duplicates while preserving order (case-sensitive)
seen = set()
unique_words = []
for word in words:
if word not in seen:
seen.add(word)
unique_words.append(word)

# Sort the words
unique_words.sort()

with open(dict_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(unique_words) + '\n')

print(f"Sorted and uniquified {dict_file}")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Preserve comments, drop blanks, and dedupe/sort case-insensitively.

Current logic sorts and dedupes comments with words, keeps blanks, and dedupes case-sensitively despite caseSensitive=false in cspell.json.

Apply:

 def sort_custom_dict():
     dict_file = Path(__file__).parent.parent / "cspell" / "custom-dict.txt"
     if not dict_file.exists():
         print(f"Dictionary file {dict_file} not found.")
         return
 
-    with open(dict_file, 'r', encoding='utf-8') as f:
-        words = f.read().splitlines()
+    with open(dict_file, 'r', encoding='utf-8') as f:
+        lines = f.read().splitlines()
 
-    # Remove duplicates while preserving order (case-sensitive)
-    seen = set()
-    unique_words = []
-    for word in words:
-        if word not in seen:
-            seen.add(word)
-            unique_words.append(word)
+    # Separate comments and words; strip whitespace; drop blanks
+    comments: list[str] = []
+    words: list[str] = []
+    for raw in lines:
+        line = raw.rstrip()
+        if not line:
+            continue
+        if line.lstrip().startswith("#"):
+            comments.append(line)
+        else:
+            words.append(line.strip())
 
-    # Sort the words
-    unique_words.sort()
+    # Dedupe case-insensitively (cspell config is case-insensitive) while preserving first-seen casing
+    seen_ci: set[str] = set()
+    unique_words: list[str] = []
+    for w in words:
+        key = w.casefold()
+        if key not in seen_ci:
+            seen_ci.add(key)
+            unique_words.append(w)
+
+    # Sort words case-insensitively but keep original casing
+    unique_words.sort(key=str.casefold)
 
     with open(dict_file, 'w', encoding='utf-8') as f:
-        f.write('\n'.join(unique_words) + '\n')
+        out = []
+        if comments:
+            out.extend(comments)
+        if comments and unique_words:
+            out.append("")  # spacer
+        out.extend(unique_words)
+        f.write('\n'.join(out) + '\n')
 
-    print(f"Sorted and uniquified {dict_file}")
+    print(f"Sorted and uniquified {dict_file}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def sort_custom_dict():
dict_file = Path(__file__).parent.parent / "cspell" / "custom-dict.txt"
if not dict_file.exists():
print(f"Dictionary file {dict_file} not found.")
return
with open(dict_file, 'r', encoding='utf-8') as f:
words = f.read().splitlines()
# Remove duplicates while preserving order (case-sensitive)
seen = set()
unique_words = []
for word in words:
if word not in seen:
seen.add(word)
unique_words.append(word)
# Sort the words
unique_words.sort()
with open(dict_file, 'w', encoding='utf-8') as f:
f.write('\n'.join(unique_words) + '\n')
print(f"Sorted and uniquified {dict_file}")
def sort_custom_dict():
dict_file = Path(__file__).parent.parent / "cspell" / "custom-dict.txt"
if not dict_file.exists():
print(f"Dictionary file {dict_file} not found.")
return
with open(dict_file, 'r', encoding='utf-8') as f:
lines = f.read().splitlines()
# Separate comments and words; strip whitespace; drop blanks
comments: list[str] = []
words: list[str] = []
for raw in lines:
line = raw.rstrip()
if not line:
continue
if line.lstrip().startswith("#"):
comments.append(line)
else:
words.append(line.strip())
# Dedupe case-insensitively (cspell config is case-insensitive) while preserving first-seen casing
seen_ci: set[str] = set()
unique_words: list[str] = []
for w in words:
key = w.casefold()
if key not in seen_ci:
seen_ci.add(key)
unique_words.append(w)
# Sort words case-insensitively but keep original casing
unique_words.sort(key=str.casefold)
with open(dict_file, 'w', encoding='utf-8') as f:
out = []
if comments:
out.extend(comments)
if comments and unique_words:
out.append("") # spacer
out.extend(unique_words)
f.write('\n'.join(out) + '\n')
print(f"Sorted and uniquified {dict_file}")

Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement comprehensive spell checking support

2 participants

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载