<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: WizMantra Academy</title>
    <description>The latest articles on DEV Community by WizMantra Academy (@wizmantra_academy).</description>
    <link>https://dev.to/wizmantra_academy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4232022%2Fbc498387-9f3e-451e-907b-cd89b9b21788.jpg</url>
      <title>DEV Community: WizMantra Academy</title>
      <link>https://dev.to/wizmantra_academy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wizmantra_academy"/>
    <language>en</language>
    <item>
      <title>Counting filler words when speech-to-text deletes them</title>
      <dc:creator>WizMantra Academy</dc:creator>
      <pubDate>Sat, 07 Nov 2026 12:34:02 +0000</pubDate>
      <link>https://dev.to/wizmantraacademy/counting-filler-words-when-speech-to-text-deletes-them-4ifd</link>
      <guid>https://dev.to/wizmantraacademy/counting-filler-words-when-speech-to-text-deletes-them-4ifd</guid>
      <description>&lt;p&gt;We wanted a one-minute speaking test that gives a learner three numbers: words a minute, filler words and long pauses. The browser's speech recognizer would do the hard part. We'd count.&lt;/p&gt;

&lt;p&gt;It turns out the transcript fights you on all three.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie 1: the model cleans up "um"
&lt;/h2&gt;

&lt;p&gt;Speech recognizers are trained to produce readable text, so "um" and "uh" mostly vanish. Count fillers from the transcript and a nervous speaker looks fluent.&lt;/p&gt;

&lt;p&gt;There's no fix for that from the page. What you can do is count the fillers that survive transcription because they're real words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Fillers that survive speech-to-text. Recognisers usually drop "um" and "uh". */&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;FILL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;um&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;umm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uhh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;er&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;erm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hmm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ah&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;basically&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;actually&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;literally&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;matlab&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;you know&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i mean&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kind of&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sort of&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;like&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Matlab" is the Hindi "I mean", and it turns up in Indian English speech often enough to earn a slot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie 2: "like" is a filler, except when it isn't
&lt;/h2&gt;

&lt;p&gt;"I like Python" isn't a filler. "It was, like, a huge refactor" is. We check the word before it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;LIKE_OK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;i|you|we|they|would|i'd|feel|feels|look|looks|sound|sounds|just|really|don't|didn't|also|not|is|was|it's|that's|seems&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;like&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;LIKE_OK&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's crude and it works well enough for a self-check. "Looks like", "feel like" and "I like" pass. A bare "like" in the middle of a clause gets counted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie 3: there's no silence in a transcript
&lt;/h2&gt;

&lt;p&gt;A transcript has no timestamps per word in this API, so you can't see a pause directly. But you can see when results arrive. If two &lt;code&gt;onresult&lt;/code&gt; events are more than two seconds apart, the speaker stopped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onresult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;gaps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a proxy, and a noisy one on slow networks, since Chrome's recognizer runs on Google's servers. For a learner who stalls for four seconds looking for a word, it's accurate enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lie 4: Android repeats itself
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;continuous = true&lt;/code&gt;, desktop Chrome sends each final result once. Android Chrome sends each new final result with the earlier text still inside it. Join them naively and every sentence appears two or three times, and your words-a-minute doubles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFinal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;finals&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;finals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="cm"&gt;/* Android Chrome repeats earlier text inside each new final result */&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;finals&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;finals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;finals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two smaller ones while we're here. The browser ends a "continuous" session early when it feels like it, so &lt;code&gt;onend&lt;/code&gt; restarts it if the timer is still running. And after &lt;code&gt;stop()&lt;/code&gt;, the last final result can take over a second to arrive, so we wait up to 1,800 ms before scoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scoring is the boring part
&lt;/h2&gt;

&lt;p&gt;Once the transcript is honest, the score is plain thresholds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;under 70 words a minute: slow&lt;/li&gt;
&lt;li&gt;120 to 160: natural&lt;/li&gt;
&lt;li&gt;over 165: fast, fine if people follow you&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fillers per minute and long pauses add to the band. That's about 40 lines. The model does the hearing; the judgement is ours, in plain &lt;code&gt;if&lt;/code&gt; statements anyone can read and argue with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://wizmantraenglishclasses.com/english-practice/english-fluency-test/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=filler-words" rel="noopener noreferrer"&gt;60-second English fluency test&lt;/a&gt;. Chrome, Edge or Safari. Firefox gets a typed fallback because it has no SpeechRecognition.&lt;/p&gt;

&lt;p&gt;Has anyone found a browser-side way to keep "um" in the transcript? I'd like to know.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Drafted with help from an AI assistant. Code is from the live tool.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Standup English for Indian developers, the 90-second version</title>
      <dc:creator>WizMantra Academy</dc:creator>
      <pubDate>Sat, 07 Nov 2026 12:27:19 +0000</pubDate>
      <link>https://dev.to/wizmantraacademy/standup-english-for-indian-developers-the-90-second-version-303c</link>
      <guid>https://dev.to/wizmantraacademy/standup-english-for-indian-developers-the-90-second-version-303c</guid>
      <description>&lt;p&gt;Your code is fine. The standup is where the remote team actually hears you, every day, for about 90 seconds. That's the slot this post is about.&lt;/p&gt;

&lt;p&gt;A lot of engineers know the feeling: you freeze in the standup, or you switch to Hindi in your head and translate while you talk.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three-line shape
&lt;/h2&gt;

&lt;p&gt;Yesterday, today, blocked. Keep each to one sentence, with one concrete noun in it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yesterday I finished the retry logic for the payment webhook.&lt;br&gt;
Today I'm writing tests for it and then picking up the login bug.&lt;br&gt;
I'm blocked on the staging keys. Could someone on infra share them after this call?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Three things make that work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A real noun.&lt;/strong&gt; "The retry logic for the payment webhook", not "that issue".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Present continuous for today.&lt;/strong&gt; "I'm writing", "I'm picking up". It sounds planned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The blocker ends in a question with a person in it.&lt;/strong&gt; "Could someone on infra..." gets an answer. "There is some dependency" gets silence.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What to drop
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Common&lt;/th&gt;
&lt;th&gt;Better&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Basically, actually, so basically&lt;/td&gt;
&lt;td&gt;(nothing, just start)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I did the needful for the ticket&lt;/td&gt;
&lt;td&gt;I fixed the ticket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I have one doubt on this&lt;/td&gt;
&lt;td&gt;I've got a question about this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Will revert by EOD&lt;/td&gt;
&lt;td&gt;I'll reply by end of day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Myself Rahul, from the backend team&lt;/td&gt;
&lt;td&gt;I'm Rahul, I work on the backend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;It is done from my side&lt;/td&gt;
&lt;td&gt;It's done on my end&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;"Basically" is the big one. It buys thinking time, and a silent half-second does the same job better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pace is the thing nobody tells you
&lt;/h2&gt;

&lt;p&gt;Most fluent speakers sit around 120 to 160 words a minute. Below 100, listeners start finishing your sentences for you. Way above 165, a non-Indian listener on a laggy call loses you.&lt;/p&gt;

&lt;p&gt;You won't know your own pace by feel. Measure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disagreeing without sounding rude or timid
&lt;/h2&gt;

&lt;p&gt;Two extremes show up in standups: silence, or a flat "No, that is wrong". Try these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"I see it a bit differently. Can I share why after standup?"&lt;/li&gt;
&lt;li&gt;"That works for me, with one concern about the migration."&lt;/li&gt;
&lt;li&gt;"Can we take that offline? It needs ten minutes."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that all three move the real discussion out of the standup. That's good standup manners anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practise it for free
&lt;/h2&gt;

&lt;p&gt;We built these as browser tools. They need no sign-up and run on a phone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wizmantraenglishclasses.com/english-practice/english-roleplay/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=standup-english" rel="noopener noreferrer"&gt;English roleplay&lt;/a&gt; has a "Meeting: disagreeing politely" scene and an HR screening call, both with branching replies.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wizmantraenglishclasses.com/english-practice/english-fluency-test/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=standup-english" rel="noopener noreferrer"&gt;60-second fluency test&lt;/a&gt; gives your words a minute, filler count and long pauses. Say tomorrow's standup into it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wizmantraenglishclasses.com/english-practice/indian-english-checker/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=standup-english" rel="noopener noreferrer"&gt;Indian English checker&lt;/a&gt;: paste your Slack update before you send it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fluency test uses the browser's speech recognizer, so it needs Chrome, Edge or Safari, and Chrome sends the audio to Google to transcribe. We don't store anything.&lt;/p&gt;

&lt;p&gt;What's the standup phrase you've heard from a teammate that you've quietly stolen? Drop it below.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Drafted with help from an AI assistant. Tool details checked against the live pages.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>remote</category>
    </item>
    <item>
      <title>Why our Indian English checker is 50 regexes and no LLM</title>
      <dc:creator>WizMantra Academy</dc:creator>
      <pubDate>Sat, 07 Nov 2026 12:23:43 +0000</pubDate>
      <link>https://dev.to/wizmantraacademy/why-our-indian-english-checker-is-50-regexes-and-no-llm-2o4</link>
      <guid>https://dev.to/wizmantraacademy/why-our-indian-english-checker-is-50-regexes-and-no-llm-2o4</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;We built the opposite for our learners: an &lt;a href="https://wizmantraenglishclasses.com/english-practice/indian-english-checker/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=regex-checker" rel="noopener noreferrer"&gt;Indian English checker&lt;/a&gt; that's 50 regular expressions in one file. Each one flags a phrase, suggests a swap, and says why.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a rule looks like
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// [pattern, replacement, kind, why]   kind: i = Indianism, s = stiff, c = too casual&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;kindly do the needful&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;/gi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;please take care of this&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Do the needful&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; is understood in India and puzzling almost everywhere else. Say what you actually need.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;prepone&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;d&lt;/span&gt;&lt;span class="se"&gt;)?\b&lt;/span&gt;&lt;span class="sr"&gt;/gi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brought forward&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bring forward&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Prepone&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; is Indian English only. Use &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;bring forward&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; or &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;move up&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;I have &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;a|some|few|a few&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt; doubts&lt;/span&gt;&lt;span class="se"&gt;?\b&lt;/span&gt;&lt;span class="sr"&gt;/gi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;In Indian English &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;doubt&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; means question. Elsewhere it means you don't believe something.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;PFA&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I've attached&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PFA is office shorthand. Many readers won't know it.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "why" string matters more than the swap. A learner who reads "outside India, &lt;em&gt;passed out&lt;/em&gt; means fainted" once doesn't need the tool the second time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why rules and not a model
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explainable.&lt;/strong&gt; Every highlight points at one phrase and one reason. A learner can argue with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It doesn't rewrite your voice.&lt;/strong&gt; Rules only touch what they match. The rest of the email stays yours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free and instant.&lt;/strong&gt; No API key in the page, no per-request cost, works offline once loaded. Our audience is mostly on phones on mobile data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing to send anywhere.&lt;/strong&gt; People paste real client emails into this. The text never leaves the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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".&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the rules lose
&lt;/h2&gt;

&lt;p&gt;Here's the rule for "revert", which in Indian office English means "reply":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;revert&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;ing|ed&lt;/span&gt;&lt;span class="se"&gt;)?\b(?=&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;to|on|with|at|me|us|by|soon|asap|today|tomorrow|after&lt;/span&gt;&lt;span class="se"&gt;)\b)&lt;/span&gt;&lt;span class="sr"&gt;/gi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reply&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Revert&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; means go back to an earlier state. Outside India it doesn't mean reply.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lookahead is there so "please revert to me" gets flagged and "revert the change" doesn't. Now type this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'll revert to the last stable release.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;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".&lt;/p&gt;

&lt;p&gt;So we patched it the regex way, with a negative lookahead listing what you revert &lt;em&gt;to&lt;/em&gt; in standard English:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;(?:&lt;/span&gt;&lt;span class="nx"&gt;back&lt;/span&gt; &lt;span class="p"&gt;)?&lt;/span&gt;&lt;span class="nf"&gt;to &lt;/span&gt;&lt;span class="p"&gt;(?:&lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;our&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;)?(?:&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;old&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;stable&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;normal&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+|&lt;/span&gt;&lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;release&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;migration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Revert to me" still gets flagged. "Revert to v1.2", "revert to the old config" and "things will revert to normal" don't.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug the test found
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;after&lt;/em&gt; the match, so on its own it never matched, and the suggestion came back unchanged: "revert" becomes "revert".&lt;/p&gt;

&lt;p&gt;The fix is to run the replacement against the rest of the text from the match onwards, then cut the tail back off:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;tail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;out&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^(?:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;rep&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also keeps the tense now: "reverted on the ticket" becomes "replied on the ticket", not "reply on the ticket".&lt;/p&gt;

&lt;p&gt;Lookaheads in a rule table are easy to write and easy to forget about when you reuse the regex somewhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phrases developers send that land badly abroad
&lt;/h2&gt;

&lt;p&gt;From the rule list, the ones that show up in Slack, PR comments and client email:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You wrote&lt;/th&gt;
&lt;th&gt;They read&lt;/th&gt;
&lt;th&gt;Try&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kindly revert&lt;/td&gt;
&lt;td&gt;Kindly undo?&lt;/td&gt;
&lt;td&gt;Please reply when you can&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Do the needful&lt;/td&gt;
&lt;td&gt;Do... what?&lt;/td&gt;
&lt;td&gt;Say the actual ask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I have a doubt&lt;/td&gt;
&lt;td&gt;You don't trust me?&lt;/td&gt;
&lt;td&gt;I have a question&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PFA&lt;/td&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;I've attached&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discuss about&lt;/td&gt;
&lt;td&gt;(doubled)&lt;/td&gt;
&lt;td&gt;Discuss&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gentle reminder&lt;/td&gt;
&lt;td&gt;Passive aggressive&lt;/td&gt;
&lt;td&gt;Quick reminder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Today itself&lt;/td&gt;
&lt;td&gt;(odd emphasis)&lt;/td&gt;
&lt;td&gt;Today&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepone the call&lt;/td&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;Move the call up&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you'd build it differently
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Drafted with help from an AI assistant. Rules quoted are from the live tool.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Using the browser's speech recognizer as a pronunciation judge</title>
      <dc:creator>WizMantra Academy</dc:creator>
      <pubDate>Sat, 07 Nov 2026 12:20:59 +0000</pubDate>
      <link>https://dev.to/wizmantraacademy/using-the-browsers-speech-recognizer-as-a-pronunciation-judge-23j2</link>
      <guid>https://dev.to/wizmantraacademy/using-the-browsers-speech-recognizer-as-a-pronunciation-judge-23j2</guid>
      <description>&lt;p&gt;Pronunciation scoring APIs charge per request and want your audio on their servers. We teach spoken English to learners in India, mostly on phones, and we wanted a free test that costs us nothing to run.&lt;/p&gt;

&lt;p&gt;So we let the browser's speech recognizer play the listener.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea: minimal pairs
&lt;/h2&gt;

&lt;p&gt;Vest and west. Thin and tin. Ship and sheep. Each pair differs by one sound, and that's exactly the sound a lot of learners merge.&lt;/p&gt;

&lt;p&gt;If you say "vest" and a speech model trained on thousands of speakers writes down "west", a human listener probably hears "west" too. That's the whole test.&lt;/p&gt;

&lt;p&gt;Which pairs you get depends on your mother tongue, because the merges are predictable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;L1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;hindi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zj&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tht&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ii&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;tamil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zj&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;bengali&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ssh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zj&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tht&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// 14 languages in all&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Hindi speaker gets V/W, Z/J, TH/T, TH/D and short I versus long EE. A Tamil speaker gets P/B and K/G, which a Hindi speaker rarely needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  One word, six guesses
&lt;/h2&gt;

&lt;p&gt;The trick is &lt;code&gt;maxAlternatives&lt;/code&gt;. Most demos read &lt;code&gt;results[0][0]&lt;/code&gt; and throw the rest away. We keep all six:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;hearOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;rec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SpeechRecognition&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechRecognition&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
  &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-IN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;continuous&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interimResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxAlternatives&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onresult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;alts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the judge looks at where the target word shows up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;judge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;          &lt;span class="c1"&gt;// s.w = target word, s.o = the other word in the pair&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unclear&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;merged&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;merged&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unclear&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If "vest" is the top guess, you said it clearly. If "west" wins, you merged the sounds. And if "vest" only turns up as the fourth guess, the model wasn't sure, and that gets labelled Unclear. The alternatives carry the model's doubt. One transcript can't.&lt;/p&gt;

&lt;p&gt;An unclear result gets one retry, with a note showing what was heard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing whose ears you're testing against
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rec.lang&lt;/code&gt; changes the listener, and for an accent test that's the most useful setting in the whole API.&lt;/p&gt;

&lt;p&gt;Set it to &lt;code&gt;en-IN&lt;/code&gt; and the model has heard a lot of Indian English, so it forgives some merges a learner makes. Set it to &lt;code&gt;en-US&lt;/code&gt; and it's stricter. The result screen says so: you tested against an Indian listener, switch to US English for a harder check.&lt;/p&gt;

&lt;p&gt;For someone preparing for a call with a US client, that's literally the question. Not "is this correct" in the abstract, but "will this listener understand me".&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your audio does leave the device.&lt;/strong&gt; Chrome's recognizer sends it to Google for processing. The page says nothing reaches WizMantra, which is true, and we don't claim more than that.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firefox has no SpeechRecognition.&lt;/strong&gt; There the test flips into ear mode: &lt;code&gt;speechSynthesis&lt;/code&gt; plays one word of the pair and you pick which one you heard. If the ear can't split two sounds, the mouth usually can't either.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laptop mics lie.&lt;/strong&gt; Fan noise and a cheap mic both produce false merges, so the result tells you to repeat any pair marked Merging before you work on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One speaker, one model.&lt;/strong&gt; It's a screening test. A tutor still has to listen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our demos, most Hindi speakers fail V/W first: "vest" comes back as "west" almost every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The test is free and needs no sign-up: &lt;a href="https://wizmantraenglishclasses.com/english-practice/pronunciation-test/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=pron-judge" rel="noopener noreferrer"&gt;English pronunciation test&lt;/a&gt;. Pick your first language, press Start, say each word once.&lt;/p&gt;

&lt;p&gt;If you've used &lt;code&gt;maxAlternatives&lt;/code&gt; for something other than search, I'd like to hear what you did with it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Drafted with help from an AI assistant. The code above is from the live tool and was checked against it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ai</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
