feat: add multi-language support (German, Portuguese) - #3402
Conversation
What's the relationship between this PR and #3403 |
fb9f77e to
9565ee1
Compare
|
In case you are not aware, there is also #2150 as an attempt at adding Portuguese support. |
a0c6cdd to
e148c7e
Compare
- Remove global compound module from harper-core/src/spell/rune/compound.rs - Remove compound import and call from MutableDictionary::from_rune_files - Create German-specific compound module at harper-core/src/language/german/spell/compound.rs - Export compound module from harper-core/src/language/german/spell/mod.rs - Integrate compound generation into German dictionary loading in german_dict.rs - Make rune and word_map modules public in harper-core/src/spell/mod.rs This change moves compound word generation from a global location to a German-specific module, allowing different languages to have their own compound word generation logic. English remains unchanged with no compound generation, while German now generates compounds from words with h, i, k, l, m, o flags. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Remove unnecessary #[cfg(not(feature = "xx"))] fallback implementations from language dictionary modules (german, portuguese, slovak). These fallback implementations were dead code because: - The language modules are only exposed when their feature is enabled (via #[cfg(feature = "xx")] pub mod language; in language/mod.rs) - When the feature is disabled, the entire module is not accessible - When the feature is enabled, only the #[cfg(feature = "xx")] versions are compiled - The #[cfg(not(feature))] versions are never used This simplifies the code and removes redundant fallback implementations that returned empty dictionaries. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
The file harper-core/src/language/dialects/english.rs was created in the feature/german-language-support branch but served no purpose: - It only re-exported types already available from dict_word_metadata - No code imported from language::dialects::english - The file didn't exist in master branch - All tests pass after removal This maintains compatibility with master by keeping English dialect types in their original location (dict_word_metadata.rs). Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Update flate2 from 1.1 to 1.1.9 - Update itertools from 0.13 to 0.15 - Update tempfile from 3 to 3.27 - Update toml build-dependency from 0.8 to 1.1 - Update build scripts to use toml 1.x API (parse::<toml::Table>) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Fix 'P' property to be preposition-only with preposition: true metadata
- Add 'I' property for pronouns with pronoun: {} metadata
- Update dictionary: change pronouns (ich, du, er, sie, es, wir, ihr) from ~~P to ~~I
- Keep prepositions (in, an, auf, aus, mit, nach, von, zu, für, bei, Nebst) as ~~P
- Add tests for preposition and pronoun metadata verification
Addresses GitHub feedback on conflating pronouns and prepositions.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
…lpers These warnings appeared when no language features (de, pt, sk) are enabled, because the Language enum only has the English variant, making the _ pattern in the match statement unreachable. The _ pattern is intentionally kept for when language features are enabled, so we suppress the warning rather than removing the pattern. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This fixes the clippy len_without_is_empty lint warning that was causing the Just Checks workflow to fail. Both WordMap and Matcher structs had public len() methods but were missing the corresponding is_empty() methods. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit adds a basic Polish language implementation to test the language architecture and demonstrate how easy it is to add new languages. Key changes: - Added Polish language module with all required components - Updated build system to support Polish dialect flags - Added comprehensive README documenting the process - Created integration tests to verify Polish support - Updated Cargo.toml with Polish feature flag The Polish implementation follows the same pattern as German, Portuguese, and Slovak, demonstrating that the architecture makes it straightforward to add new languages by: 1. Copying the template structure 2. Updating config.toml 3. Implementing the LanguageModule trait 4. Adding the feature to Cargo.toml Architecture improvements identified: - The build system successfully auto-generates all necessary integration code - Dialect flag deserialization is properly extended for new languages - Language detection and parsing work out of the box - The only tedious part is building comprehensive dictionaries and grammar rules Future work for production-ready Polish: - Expand dictionary with comprehensive word list - Implement Polish-specific spell checking rules - Add grammar checking rules - Create Polish-specific Weir rules - Add comprehensive test coverage Generated files updated by build system: - harper-core/src/language/mod.rs - harper-core/src/language/languages.rs - harper-core/src/language/registry.rs - harper-core/src/language/dialects/dialect_flags.rs - harper-wasm/src/generated_dialect.rs
hippietrail
left a comment
There was a problem hiding this comment.
Things I'm noticing at a glance. Maybe it's just earlier in the process than I'd assumed?
| let dict = mutable_german_dictionary(); | ||
|
|
||
| // Test that pronouns have the pronoun metadata set | ||
| let pronouns = ["ich", "du", "er", "sie", "es", "wir", "ihr"]; |
There was a problem hiding this comment.
Out of interest, are all the pronouns in here somewhere, or overlooked? These seem to only cover the nominative case? (I haven't dug through the whole source, nor did I double-check the following list)
- deiner: of you (singular) — Genitive
- dich: you (singular) — Accusative
- dir: to you (singular) — Dative
- euch: you all / to you all — Accusative / Dative
- euer: of you all — Genitive
- ihm: to him / to it — Dative
- ihn: him — Accusative
- ihnen / Ihnen: to them / to You (formal) — Dative
- ihrer / Ihrer: of her / of them / of You (formal) — Genitive
- meiner: of me — Genitive
- mich: me — Accusative
- mir: to me — Dative
- seiner: of him / of it — Genitive
- Sie: You (formal) — Nominative / Accusative
- uns: us / to us — Accusative / Dative
- unser: of us — Genitive
There was a problem hiding this comment.
Thank you for the review. The German support is still poor, I know. Right now, I am still focussing on making the language system structure sound and extensible. Your observation is correct and helpful, this is not complete yet
Implement comprehensive dictionary validation and testing framework tools: Dictionary Tools (Point 2): - validate_language_dict.py: Dictionary format validator with checks for file existence, format validation, flag consistency, duplicates, Unicode - language_stats.py: Dictionary statistics tool showing word counts, flag distribution, length analysis, and flag coverage - dictionary_diff.py: Dictionary comparison tool for cross-language analysis Testing Framework (Point 3): - generate_language_tests.py: Test template generator for new languages - run_all_language_tests.py: All-languages integration test runner New just recipes: - language-validate: Validate dictionary files - language-stats: Show dictionary statistics - language-diff: Compare dictionaries between languages - language-generate-tests: Generate integration test templates - language-generate-all-tests: Generate all test types - language-all-test: Run integration tests for all languages Updated documentation in harper-core/src/language/README.md with usage examples and descriptions for all new tools. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Changed 19 existing pronoun entries from incorrect flags (N/M/V) to ~~I (pronoun) - Added 4 missing formal pronouns: Sie, Ihnen, Ihrer, Ihre - Updated entry count from 233538 to 233542 - Replaced generic auto-added comments with descriptive pronoun comments Pronouns corrected: - Personal pronouns: ich, du, er, sie, es, wir, ihr, sie - Possessive pronouns: mein, dein, sein, ihr, unser, euer, Ihr, Ihre, Ihrer, ihrer - Object pronouns: mich, dich, ihm, ihr, uns, euch, ihnen, Ihnen - Formal pronouns: Sie, Ihnen, Ihre, Ihrer This improves German grammar checking accuracy by ensuring pronouns are correctly identified and not flagged as incorrect when used in proper context. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Resolves merge conflicts: - harper-core/Cargo.toml: Combined boxcar dependency (from master) with flate2 dependency (from feature branch) - harper-core/src/lib.rs: Combined test imports reorganization (from feature branch) with create_test_pool macro (from master) Architecture note: The conflicts appeared in infrastructure files (Cargo.toml, lib.rs) rather than in the language implementation itself. This indicates that while the German language feature added new language modules (de, pt, sk, pl), it also modified core infrastructure (added language/ directory, refactored English into the language module system). The user's concern about English remaining 'special' is valid - the feature branch refactored English to fit the new LanguageModule architecture, which may make merging upstream changes from master more difficult. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
|
I noticed some oddities in the latest commit message.
These are not possessive pronouns. English speakers who are not linguistically aware use this terminology for words: my, our, your, his, her, its, their - but those are possessive adjectives/determiners and the actual possessive pronouns in English are: mine, ours, yours, his, hers, theirs ('his' does double-duty.) They actual possessive pronouns are: meiner, deiner, seiner, ihrer, unserer, euerer, Ihrer (which also does double-duty.) Normally what in English we call the possessive is the genitive in German, but my knowledge falls off here so maybe possessive is correct for this second set, but it's not a 'case', since each of these possessive pronouns are inflected for gender, number, and case. Example: meiner, meine, meines, meinen. Now I'm not a real linguist, justy a hobbyist, and my German is just tourist level and rusty at that, so I've surely made mistakes and omissions, but hopefully these are things to consider. |
…tions ## Compound Noun Generation - Added compound formation flags (h,i,k,l,m,o) to 40+ common nouns - Enables automatic generation of compound nouns like: - Hauswand, Schuhhersteller, Verwaltungssitz, Arbeitsplatz, Bundestag - Konzernobergesellschaft, Fußbett, Bildschirm, Dampfschiff, Handwerk - Words now properly participate in compound formation with appropriate interfixes ## Preposition Classification - Fixed misclassified prepositions: - unter: ~N → ~~P - durch: ~~N → ~~P - ohne: ~~N → ~~P - seit: ~~NX → ~~P - vor: ~~NY → ~~P - über: ~~M → ~~P - hinter: ~N → ~~P - neben: ~~V → ~~P - zwischen: ~~Z → ~~P ## Vocabulary Additions - Added proper noun: Birkenstock - Added technical terms: börsennotiert, steuertaktisch, Kanalinsel - Added domain-specific words: Fußbett, Einlage - Added missing base nouns with compound flags: Wand, Schuh, Hersteller, Verwaltung, Sitz, Konzern, Ober, Gesellschaft, Fuß, Arbeit, Platz, Bild, Schirm, Dampf, Schiff, Bund, Tag ## Testing Framework Improvements - Added German-specific dictionary loading with compound generation - Enabled 'de' feature flag for German language support ## Testing - All compound noun generation tests pass - All preposition recognition tests pass - Existing German tests continue to work Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Implement Phase 1-5 of the merge-friendly language architecture plan: - Add 'multilingual' feature flag to harper-core that gates the entire language module system (including English, German, Polish, Portuguese, Slovak) - Feature-gate pub mod language and Language/LanguageFamily exports in lib.rs - Keep English in language module system using type aliases to original Dialect types - Update harper-ls, harper-wasm, harper-cli to forward multilingual feature - Fix test files to use Dialect instead of EnglishDialect and correct file paths - Update harper-wasm import to use Dialect type alias This ensures: 1. harper-core compiles both with and without multilingual feature 2. English uses original code paths (dict_word_metadata.rs, language_detection.rs) 3. No dual representation - language/english/ uses type aliases to original types 4. Upstream English changes from master will merge cleanly 5. Minimal merge conflicts (only infrastructure files like Cargo.toml) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Add section explaining the Feature Flag Architecture - Document the multilingual master feature and individual language features - Explain behavior when multilingual is enabled/disabled - Update feature forwarding note to mention the multilingual feature - Add note about English using original implementation when multilingual is disabled Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Fix import ordering in harper-desktop and harper-ls to match rustfmt expectations - Fix clippy field_reassign_with_default error in German compound spell module - Add multilingual feature flag to harper-desktop Cargo.toml - Update testing_framework to use multilingual feature instead of de This resolves the Just Checks workflow failure that was preventing CI from passing. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
…gual support The multilingual feature with German, Portuguese, Polish, and Slovak dictionaries increases the WASM bundle size beyond the previous 30 MB limit. This adjustment allows the Obsidian plugin to include full language support. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Fix unused variable 'result' in polish_integration_test.rs by prefixing with underscore - Remove redundant assertion that was always true - This resolves the GitHub workflow failure caused by -D warnings flag Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Move manual-only test files to .archive/manual_test_scripts/: German language: - test_german_noun_verification.py - test_adjective_declension.py - german_noun_verification.expected.md Misc scripts (not referenced by justfile or CI): - check_language_features.py - cleanup_redundant.py - convert_*_plurals.py (multiple) - convert_verbs*.py (multiple) - deduplicate_dictionary.py - convert_en_plurals.py These files were for manual/offline testing only and not run by automated tests. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
…k script - Remove test_polish_integration.rs which was a temporary development file - Add scripts/check_language_features.py for validating feature consistency - Improve language coverage scripts to handle fallback dictionary paths Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Change harper-wasm/pkg to harper-wasm to match the actual package.json location. This fixes Dependabot failures where it could not resolve the workspace dependency. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This large development file (566KB) is only used by Python scripts in the .archive/ directory and doesn't need to be tracked in the main repository. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
- Added compound flags (h, i, k, l, m, o, q) to base words to enable automatic compound generation - Removed redundant compound nouns that can now be generated automatically - Added just language-add-word recipe for validated word addition with flag validation - Added validate_flags.py script to validate flags against annotations.json - Enhanced compound.rs with better documentation and adjective compound support - Improved annotations.json with compound formation rules - Verified key compounds like vergnügungssteuerpflichtig now work through generation - Dictionary reduced by removing explicit compound entries while maintaining coverage Changes: - Added compound flags to ~100+ base words (art, fall, fach, büro, etc.) - Removed ~20+ redundant compound nouns (artspezifisch, bahnspezifisch, etc.) - Enhanced development tooling for language support Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
…ancements - Add 40+ new German words from various domains including footwear, business, and technical terms - Clean up duplicate dictionary entries (67 redundant entries removed) - Enhance language-coverage just recipe to use native Rust implementation - Add coverage analysis module to testing framework - Maintain compound word generation efficiency at 6.18x Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Summary of this PR (human generated)
Adds comprehensive multi-language support to harper, enabling grammar and spell checking for German and Portuguese in addition to English. Introduces a modular language architecture with compressed dictionaries, dialect detection, and language-specific linters.
See #2654 for the discussion on different approaches on the language feature. I would be very happy for suggestions or even PRs on this branch so we can make this happen in a solid architecture.
Details (AI generated)
Language System
• Language enum in harper-core/src/languages.rs: Represents all supported languages with their dialects (English, German, Portuguese)
• LanguageFamily enum: Broad language categories without dialect specification
• ProseLanguage enum in registry.rs: Maps languages to their prose handling
Dictionary Handling
• Compressed embedding: Dictionaries stored as .dict.gz files, loaded via include_bytes! + runtime gzip decompression
• Per-language dictionaries: Separate dictionaries for each language under harper-core/src/language/{lang}/
• Metadata: Portuguese includes stress-based annotation rules for accurate pluralization
Modular Structure