Why our Indian English checker is 50 regexes and no LLM
Paste "Kindly do the needful and revert at the earliest" into any LLM and ask it to fix the tone. You'll get a nice answer. You'll also get a rewritten email that sounds like the LLM, and no idea which three phrases were the problem. We built the opposite for our learners: an Indian English checker that's 50 regular expressions in one file. Each one flags a phrase, suggests a swap, and says why. What a rule looks like // [pattern, replacement, kind, why] kind: i = Indianism, s = stiff, c = too casual [/\bkindly do the needful\b/gi, "please take care of this", "i", "\"Do the needful\" is understood in India and puzzling almost everywhere else. Say what you actually need."], [/\bprepone(d)?\b/gi, function (m, d) { return d ? "brought forward" : "bring forward"; }, "i", "\"Prepone\" is Indian English only. Use \"bring forward\" or \"move up\"."], [/\bI have (a|some|few|a few) doubts?\b/gi, ..., "i", "In Indian English \"doubt\" means question. Elsewhere it means you don't believe something."], [/\bPFA\b/g, "I've attached", "s", "PFA is office shorthand. Many readers won't know it."], The "why" string matters more than the swap. A learner who reads "outside India, passed out means fainted" once doesn't need the tool the second time. Why rules and not a model Explainable. Every highlight points at one phrase and one reason. A learner can argue with it. It doesn't rewrite your voice. Rules only touch what they match. The rest of the email stays yours. Free and instant. No API key in the page, no per-request cost, works offline once loaded. Our audience is mostly on phones on mobile data. Nothing to send anywhere. People paste real client emails into this. The text never leaves the browser. For this job, the catalogue of Indianisms is finite and well known. You don't need a model to know that "cope up with" should be "cope with". Where the rules lose Here's the rule for "revert", which in Indian office English means "reply": [/\brevert(ing|ed)?\b(?= (to|on|with|at|me|us|by|soon|asap|today|tomorrow|after)\b)/gi, "reply", "i", "\"Revert\" means go back to an earlier state. Outside India it doesn't mean reply."], The lookahead is there so "please revert to me" gets flagged and "revert the change" doesn't. Now type this: I'll revert to the last stable release. The old version marked it red as an Indianism. Every developer reading this knows that's wrong, and the rule couldn't, because it has no idea what a release is. "Revert back to the previous version" was worse: the suggested rewrite was "reply to the previous version". So we patched it the regex way, with a negative lookahead listing what you revert to in standard English: (?! (?:back )?to (?:the |a |our |that |this )?(?:last|previous|old|original|stable|default|normal|v?\d+|commit|version|release|build|backup|branch|main|config|migration)\b) "Revert to me" still gets flagged. "Revert to v1.2", "revert to the old config" and "things will revert to normal" don't. That's the honest trade. A regex knows the phrase, so every new context is another hand-written exception. A model knows the sentence and would never have needed the list. The bug the test found Writing that test turned up a second, quieter bug. The tool built each suggested fix by re-running the rule on the matched word alone, "revert". But the rule ends in a lookahead that needs the words after the match, so on its own it never matched, and the suggestion came back unchanged: "revert" becomes "revert". The fix is to run the replacement against the rest of the text from the match onwards, then cut the tail back off: var tail = src.slice(h.e), out = src.slice(h.s).replace(new RegExp("^(?:" + r[0].source + ")", flags), r[1]); var rep = out.slice(0, out.length - tail.length); It also keeps the tense now: "reverted on the ticket" becomes "replied on the ticket", not "reply on the ticket". Lookaheads in a rule table are easy to write and easy to forget about when you reuse the regex somewhere else. Phrases developers send that land badly abroad From the rule list, the ones that show up in Slack, PR comments and client email: You wrote They read Try Kindly revert Kindly undo? Please reply when you can Do the needful Do... what? Say the actual ask I have a doubt You don't trust me? I have a question PFA ? I've attached Discuss about (doubled) Discuss Gentle reminder Passive aggressive Quick reminder Today itself (odd emphasis) Today Prepone the call ? Move the call up All of these work fine inside India. A reader in Toronto or Berlin just doesn't share them, and a lot of us write for that reader every day now. If you'd build it differently The tempting middle ground is rules first, then an LLM pass only on sentences a rule flagged, to catch the contexts our exception list will always miss. It'd cost a fraction of a full rewrite. We haven't built it. If you've done a hybrid like this, I'd like to know how you kept the model from rewriting the rest of the text. Drafted with help from an AI assistant. Rules quoted are from the live tool.
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to