https://github.com/reececomo/gcomply
Lightweight automatic grammar agreement engine for JavaScript/TypeScript
https://github.com/reececomo/gcomply
grammar l10n language localization natural-language nlp
Last synced: 8 months ago
JSON representation
Lightweight automatic grammar agreement engine for JavaScript/TypeScript
- Host: GitHub
- URL: https://github.com/reececomo/gcomply
- Owner: reececomo
- License: mit
- Created: 2025-05-21T02:18:26.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-09-01T08:40:17.000Z (10 months ago)
- Last Synced: 2025-09-01T10:44:38.902Z (10 months ago)
- Topics: grammar, l10n, language, localization, natural-language, nlp
- Language: TypeScript
- Homepage: http://npmjs.org/gcomply
- Size: 207 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
🪡 GComply
Beautiful and natural-sounding text in human interfaces.
```ts
`Add ${count} person to group.`
// ❌ "Add 2 person to group."
g`Add ${count} person to group.`
// ✅ "Add 2 people to group."
```
Lightweight automatic grammar agreement.
> [!WARNING]
> **Experimental**: This is an experimental JavaScript API for automatic grammar
> agreement, modeled after the equivalent
> [Swift API](https://developer.apple.com/documentation/foundation/inflectionrule).
## **🚀 Mission**
- ✅ **What it is:**
A lightweight engine for automatic grammar agreement – scoped specifically for human
interfaces in software products. Provide fast, automatic grammar agreement to cover ~99%
of real-world cases. Take the edge-case handling out of UI.
- ❌ **What it is NOT:**
Perfect or feature-complete grammar correction, stemming/lemmatization, lexical analysis,
or sentiment analysis. This package will never
📘 Read more: Distinction from ICU Intl.MessageFormat
**Intl.MessageFormat** provides manual support for plural/selects. But it is entirely
manual, and up to developers to predict all variance. It's also very challenging to
correctly translate any string where a parameter (i.e. a noun) is interpolated.
**Example:**
```ts
const notification = t("I was in {country}")
// German: "Ich war in {country}"
const switzerland = t("Switzerland")
// German: "die Schweiz"
notification.format({ country: switzerland })
// "Ich war in die Schweiz" ❌
// The feminine dative article is "der" (not
// "die") so it should instead be:
// "Ich war in der Schweiz" ✅
```
In this example if you supported 180+ countries, you might have a much bigger problem.
So to summarize, **ICU MessageFormat** is a great tool, but its focused primarily on a
different problem.
### Add plurals
```ts
import { Grammar, Plurals } from "gcomply";
Plurals.getLang("en").addTagged(Grammar.PartOfSpeech.noun,
{ one: "sausage", other: "sausages" },
{ one: "twist", other: "twists" },
);
```
## ✨ Features
- ⚡️ **Instant grammar agreement** — plurals, gender, articles, etc.
- 📦 **Highly pluggable** — compatible with any other framework
- 🌐 **Localizable** — add support for any natural language
- 🪶 **Lightweight** — <5kB, zero dependencies
Add custom transforms, domain terminology, nouns, pronouns, and more.
## API Usage
### Simple usage
- Syntax: ``` g`` ```
The `g` tagged template will coerce inline grammar
(in accordance to any global options).
```ts
import { g } from "gcomply";
let views = content.viewCount,
shares = content.shareCount
let text = g`${views} new views, ${shares} new shares`
// "35 new views, 1 new share"
```
### Complex grammar
- Syntax: `inflect(text, options?)`
The `inflect()` function provides a little more flexibility for complex
grammatical agreement, and may also be passed additional external options:
```ts
import { inflect } from "gcomply";
let text = "Votre conseiller est prêt."
let opts = {
language: "fr",
morphology: { grammaticalGender: "feminine" }
}
inflect(text) // "Votre conseiller est prêt."
inflect(text, opts) // "Votre conseillère est prête."
```
> [!NOTE]
> **Terminology:**
>
> Parts of the API terminology is modeled to be consistent with the emerging equivalent
> Swift APIs for
> [morphology](https://developer.apple.com/documentation/foundation/morphology)
> and [inflection](https://developer.apple.com/videos/play/wwdc2023/10153/).
>
> Notably though, there is **no direct proxy** for Swift's
> [AttributedString](https://developer.apple.com/documentation/foundation/attributedstring)
> in JavaScript.
## Implementation status
These are the Swift agreement features:
| Status | Agreement Type | Methodology | Code Changes | Description
| --- | ---------------------- | ----------------------- | ------------ | ---
| partial | `inflect` | Proximity-based | No | Reference neighboring elements.
| ❌ | `agreeWithArgument` | Explicit reference, same string | No | Directly reference other elements in the strings.
| ❌ | `agreeWithConcept` | Explicit reference, injected | Yes | Agree with a `Concept` passed in via context.
> [!NOTE]
> **Source:** See [WWDC2023 @ 6:15](https://developer.apple.com/videos/play/wwdc2023/10153/)
## 🛠️ Contributing
Contributions are welcome, such as:
- New language packs
- More granular inflection rules
- Bug fixes and test cases
- Integrations for other frameworks or i18n tools
> [!Important]
> Keep in mind, the goal of this package is not to provide perfect and comprehensive
> language support that covers all possible permutations out-of-the-box.