Breaking Free: How to Fix LanguageTool's Overleaf Block (A Technical Deep-Dive)

LanguageTool started blocking Overleaf with a "temporarily disabled" message. We reverse-engineered the extension, found the culprit, and created a client-side patch that bypasses the restriction entirely. Here's how we did it and how you can fix it too.

Breaking Free: How to Fix LanguageTool's Overleaf Block (A Technical Deep-Dive)

When your favorite grammar checker decides to ghost your favorite LaTeX editor 📝

🤖
This article, in contrast to all the other posts in this blog, has been mostly written by AI to provide immediate help to any other person in the same situation.

TL;DR

LanguageTool started blocking Overleaf with a "temporarily disabled" message. We reverse-engineered the extension, found the culprit, and created a client-side patch that bypasses the restriction entirely. Here's how we did it and how you can fix it too.


The problem: When extensions go rogue

If you're a LaTeX user who relies on LanguageTool for grammar checking, you've probably hit this frustrating wall:

Lo sentimos, LanguageTool ha deshabilitado temporalmente el soporte 
para este sitio web. Estamos trabajando en una solución. 
Debería ser cuestión de días.

Translation: "Sorry, LanguageTool has temporarily disabled support for this website. We're working on a solution. It should be a matter of days."

Screenshot of the error (in Spanish)

The Investigation: Going Down the Rabbit Hole

Step 0: Asking for support

As a LanguageTool user and suscriber I have access to the support team. I reached them with some screenshoots and, after some interactions, they replied me that they were aware of the issue and the haven't had and ETA.
The offered me a reimbursement, but I'd like to keep using Language Tool, as I found it really useful!

Step 1: Finding the Smoking Gun

First, I dug into the extension's localization files to trace where this message comes from. In _locales/es/messages.json, there it was:

{
  "siteTemporarilyUnsupported": {
    "message": "Lo sentimos, LanguageTool ha deshabilitado temporalmente..."
  }
}

The message key siteTemporarilyUnsupported was our first clue.

Step 2: Following the Breadcrumbs

Using grep to search through the minified JavaScript files, I found this logic in popup.js:

ff.isDomainSupported(Z_) ? 
  ff.isDomainExcludedByGroupPolicy(Z_) && (d.supported=!1, d.unsupportedMessage=In.getMessage("siteDisabledPerGroupPolicy")) : 
  (d.supported=!1, d.unsupportedMessage=In.getMessage("siteTemporarilyUnsupported"))

Bingo! When isDomainSupported() returns false, it triggers our dreaded error message.

Step 3: The Remote Config Revelation

Digging deeper, I discovered that LanguageTool uses a remote configuration system. The extension fetches domain blacklists from:

https://languagetool.org/webextension_config.json

The isDomainSupported function checks against this dynamically updated list:

isDomainSupported(e) {
  return !this._configuration || 
         !this._configuration.unsupportedDomains.includes("*") && 
         !Hr._isListContainsDomain(this._configuration.unsupportedDomains, e)
}

The thing here is that overleaf.com was not on this list! Only "seleniumbase.io" appears at the moment of writing.

Step 4: The Domain Matching Logic

The _isListContainsDomain function is particularly clever—it supports wildcard subdomain matching:

function Mt(e,t) {
  const r = Ut(t);  // Normalize domain
  return (e||[]).some(e => {
    const t = Ut(e);
    return t === r || r.endsWith("." + t)  // Exact OR subdomain match
  });
}

This means if overleaf.com is blocked, so are www.overleaf.com, v2.overleaf.com, etc.

The Solution: Client-Side Liberation

The Strategy

Instead of trying to fight the remote configuration (which we can't control), we implement a client-side override. The beauty of browser extensions is that once you have the code, you can modify it.

The Implementation

The fix is elegantly simple. We modify the isDomainSupported function to always return true for Overleaf domains, regardless of what the remote config says:

isDomainSupported(e) {
    // Always allow overleaf.com and its subdomains
    if(e && (e.includes('overleaf.com') || e.endsWith('overleaf.com'))) {
        return true;
    }
    // Original logic continues...
    return !this._configuration || 
           !this._configuration.unsupportedDomains.includes("*") && 
           !Hr._isListContainsDomain(this._configuration.unsupportedDomains, e)
}

Files That Need Patching

LanguageTool's architecture spreads this function across multiple contexts:

  • background.js - Main extension logic
  • content.js - Injected page scripts
  • popup.js - Extension popup interface
  • validator/validator.js - Grammar validation engine
  • toolbox/toolbox.js - Writing tools interface
  • options/options.js - Settings management
  • And several others...

Each file contains its own minified version of the domain checking logic, so they all need the same patch.

Happy LaTeX writing, everyone! 🎉