<?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: davlat aliev</title>
    <description>The latest articles on DEV Community by davlat aliev (@davlat_aliev_392c20ec5c92).</description>
    <link>https://dev.to/davlat_aliev_392c20ec5c92</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%2F4105526%2F84e43966-bfea-4bc1-b467-5ee3dc45f42d.jpg</url>
      <title>DEV Community: davlat aliev</title>
      <link>https://dev.to/davlat_aliev_392c20ec5c92</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davlat_aliev_392c20ec5c92"/>
    <language>en</language>
    <item>
      <title>Your React app unmounts when a reader turns on Chrome translate</title>
      <dc:creator>davlat aliev</dc:creator>
      <pubDate>Fri, 04 Sep 2026 07:19:13 +0000</pubDate>
      <link>https://dev.to/davlat_aliev_392c20ec5c92/your-react-app-unmounts-when-a-reader-turns-on-chrome-translate-2hn3</link>
      <guid>https://dev.to/davlat_aliev_392c20ec5c92/your-react-app-unmounts-when-a-reader-turns-on-chrome-translate-2hn3</guid>
      <description>&lt;p&gt;Look for this in your error tracker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node':
The node to be removed is not a child of this node.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no local repro. The affected sessions have nothing in common, until you notice they had&lt;br&gt;
page translation on.&lt;/p&gt;

&lt;p&gt;I spent about a month measuring what translators do to a live DOM. Chrome, Edge, Firefox, Yandex,&lt;br&gt;
and Google's &lt;code&gt;translate_a/element.js&lt;/code&gt; widget. Every figure here comes from a raw recording, taken&lt;br&gt;
2026-09-02 on Windows against Chrome 151.&lt;/p&gt;
&lt;h2&gt;
  
  
  What actually happens to your node
&lt;/h2&gt;

&lt;p&gt;Chrome does not edit your text node. It builds a new one, wraps it, puts the wrapper where yours&lt;br&gt;
was, and detaches yours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr1vr324s3aezon3iqk3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr1vr324s3aezon3iqk3i.png" alt="Before and after: the text node is replaced by a font wrapper and the original is detached" width="799" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the markup that replaced &lt;code&gt;There are 4 lights!&lt;/code&gt; on a page translated to Dutch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;font&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"vertical-align: inherit;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;font&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"vertical-align: inherit;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Er zijn 4 lampen!&lt;span class="nt"&gt;&amp;lt;/font&amp;gt;&amp;lt;/font&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yandex does the same thing with &lt;code&gt;&amp;lt;ya-tr-span&amp;gt;&lt;/code&gt; and keeps your source string in a &lt;code&gt;data-value&lt;/code&gt;&lt;br&gt;
attribute.&lt;/p&gt;

&lt;p&gt;React's fiber still points at the detached original. That gives you two failures. &lt;code&gt;removeChild&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;insertBefore&lt;/code&gt; throw, because the node has no parent any more. And &lt;code&gt;node.nodeValue = '...'&lt;/code&gt;&lt;br&gt;
throws nothing at all, while reaching nobody.&lt;/p&gt;

&lt;p&gt;The crash is the loud half. The freeze is the one that never reaches your error tracker.&lt;/p&gt;
&lt;h2&gt;
  
  
  The JSX that triggers it
&lt;/h2&gt;

&lt;p&gt;Two shapes. A conditional text node with a sibling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;There are 4 lights!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; (status)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; matters. Without a sibling, React clears the parent with &lt;code&gt;textContent&lt;/code&gt; and nothing&lt;br&gt;
throws. With one, the string becomes a real text node and React calls &lt;code&gt;removeChild&lt;/code&gt; on it.&lt;/p&gt;

&lt;p&gt;And any text with a value in the middle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;There are &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; lights!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The literal text on both sides forces three separate text nodes. That is what freezes.&lt;/p&gt;

&lt;p&gt;shuhei described the first shape in &lt;a href="https://github.com/facebook/react/issues/11538" rel="noopener noreferrer"&gt;facebook/react#11538&lt;/a&gt;&lt;br&gt;
in 2018. Dan Abramov closed it won't-fix.&lt;/p&gt;
&lt;h2&gt;
  
  
  The guard everyone pastes
&lt;/h2&gt;

&lt;p&gt;From that thread:&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;const&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;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeChild&lt;/span&gt;
&lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeChild&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;child&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;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&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;arguments&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;One React app, three setups, same translation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flkaxwobmamlc6bvu9p0n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flkaxwobmamlc6bvu9p0n.png" alt="Three setups compared: crash, frozen, correct" width="799" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The guard stops the throw. It leaves the app frozen, keeps deleted text on screen, and lets a&lt;br&gt;
flipped ternary render both branches. It trades a crash you can see for a bug you cannot.&lt;/p&gt;
&lt;h2&gt;
  
  
  Not every browser
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Detaching&lt;/th&gt;
&lt;th&gt;In place&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Engines&lt;/td&gt;
&lt;td&gt;Chrome, Yandex, the Google widget&lt;/td&gt;
&lt;td&gt;Edge, Firefox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What lands in the DOM&lt;/td&gt;
&lt;td&gt;a wrapper element, original detached&lt;/td&gt;
&lt;td&gt;the text node is rewritten, no wrapper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Marker&lt;/td&gt;
&lt;td&gt;inline &lt;code&gt;vertical-align: inherit&lt;/code&gt;, or eight &lt;code&gt;data-*&lt;/code&gt; attributes&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;_msttexthash&lt;/code&gt; on Edge, nothing on Firefox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your write reaches the screen&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Edge and Firefox leave the node connected, so your writes land. A counter driven once a second&lt;br&gt;
reached 6 in both. They are narrower, not immune: when they merge adjacent text runs they detach&lt;br&gt;
too, 2 nodes against Chrome's 3 on the same probe.&lt;/p&gt;

&lt;p&gt;One detection trap, since the usual advice is to spot Google's wrapper by its vertical alignment:&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="nf"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;verticalAlign&lt;/span&gt; &lt;span class="c1"&gt;// "baseline", the cascade resolved it&lt;/span&gt;
&lt;span class="nx"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verticalAlign&lt;/span&gt;             &lt;span class="c1"&gt;// "inherit", the fingerprint you want&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Chrome only translates what is on screen
&lt;/h2&gt;

&lt;p&gt;I fired ten signals at an idle translator, plus a no-signal control, each against the same&lt;br&gt;
untranslated node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30w5t3li8g4vmlm73gfr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30w5t3li8g4vmlm73gfr.png" alt="Ten signals and a control. Only scrollIntoView worked, at 168ms" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One worked. Nine did nothing for 10 seconds, including a real mouse wheel and a real mouse move&lt;br&gt;
generated by the browser. So trusted input is not the trigger, and neither is scrolling the&lt;br&gt;
window. The element has to enter the viewport.&lt;/p&gt;

&lt;p&gt;Chrome's translator is not a MutationObserver over your page. It re-scans what becomes visible.&lt;/p&gt;
&lt;h2&gt;
  
  
  The conclusion I got wrong
&lt;/h2&gt;

&lt;p&gt;I had written down that Chrome never repairs a restored text node. I had a probe proving it.&lt;/p&gt;

&lt;p&gt;The probe sat below the fold.&lt;/p&gt;

&lt;p&gt;With the element in view, Chrome repaired the restored node in 210ms. Off screen it never did.&lt;br&gt;
A probe that only ever ran below the fold would have shipped the wrong claim, and for two days it&lt;br&gt;
did.&lt;/p&gt;
&lt;h2&gt;
  
  
  What a repair costs the reader
&lt;/h2&gt;

&lt;p&gt;Once the node is detached you have two options. Restore the original and let the translator catch&lt;br&gt;
up, or write the new value into the wrapper the translator already built.&lt;/p&gt;

&lt;p&gt;Five replicates of four updates, sampled every 50ms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Across the 20 updates&lt;/th&gt;
&lt;th&gt;Restore and retranslate&lt;/th&gt;
&lt;th&gt;Write into the wrapper&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Shortest update&lt;/td&gt;
&lt;td&gt;100ms of source language&lt;/td&gt;
&lt;td&gt;0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median update&lt;/td&gt;
&lt;td&gt;150ms&lt;/td&gt;
&lt;td&gt;0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A sequence of four&lt;/td&gt;
&lt;td&gt;500 to 600ms&lt;/td&gt;
&lt;td&gt;0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A price that changes once is a flash nobody reports. A counter pays it every tick.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where writing into the wrapper stops working
&lt;/h2&gt;

&lt;p&gt;Splicing a new digit into an already-translated sentence works in Dutch. In Russian it breaks the&lt;br&gt;
grammar. &lt;code&gt;Intl.PluralRules('ru')&lt;/code&gt; puts 4 in &lt;code&gt;few&lt;/code&gt; and 7 in &lt;code&gt;many&lt;/code&gt;, and the noun follows the&lt;br&gt;
category, so &lt;code&gt;Здесь 4 лампочки!&lt;/code&gt; must not become &lt;code&gt;Здесь 7 лампочки!&lt;/code&gt;. An early build of mine&lt;br&gt;
shipped exactly that.&lt;/p&gt;

&lt;p&gt;The merge now refuses when the plural category, the digit count or the sentence shape changes, or&lt;br&gt;
when the locale is unknown. On refusal the reader gets the right number in the source language.&lt;br&gt;
That is a real loss, and Dutch and German report &lt;code&gt;other&lt;/code&gt; at every count, so it stays invisible in&lt;br&gt;
the languages this was developed against.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two things worth checking in your own app
&lt;/h2&gt;

&lt;p&gt;Attributes get translated too: &lt;code&gt;alt&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;placeholder&lt;/code&gt;, &lt;code&gt;aria-label&lt;/code&gt; and a submit &lt;code&gt;value&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;data-*&lt;/code&gt; attributes and &lt;code&gt;meta[name=description]&lt;/code&gt; are left alone.&lt;/p&gt;

&lt;p&gt;Every engine also rewrites &lt;code&gt;&amp;lt;html lang&amp;gt;&lt;/code&gt;, and Chrome appends &lt;code&gt;class="translated-ltr"&lt;/code&gt;. If you use&lt;br&gt;
Next.js, that lands before hydration and gives you a mismatch warning that no runtime library can&lt;br&gt;
prevent. &lt;code&gt;suppressHydrationWarning&lt;/code&gt; on the root element is the fix, and it only covers that one&lt;br&gt;
element's own attributes.&lt;/p&gt;
&lt;h2&gt;
  
  
  What came out of it
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;translate-shield&lt;/code&gt; forwards React's writes into the wrapper instead of restoring the node. Zero&lt;br&gt;
dependencies, about 15 kB packed. On Edge and Firefox it does nothing, which is correct there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;translate-shield
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initTranslateShield&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;translate-shield&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;initTranslateShield&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not translate anything and it does not replace an i18n library. If you only want the lint&lt;br&gt;
rule, &lt;a href="https://www.npmjs.com/package/eslint-plugin-react-google-translate" rel="noopener noreferrer"&gt;eslint-plugin-react-google-translate&lt;/a&gt;&lt;br&gt;
catches the risky JSX shapes before they ship, and is worth running either way.&lt;/p&gt;

&lt;p&gt;There is a &lt;a href="https://google-translate-simulation.netlify.app/" rel="noopener noreferrer"&gt;live demo&lt;/a&gt; that runs the protected&lt;br&gt;
and unprotected versions side by side in your own browser, in two separate documents, because the&lt;br&gt;
patch covers a whole document and one page could not host an honest control.&lt;/p&gt;

&lt;p&gt;Every figure above comes from a JSON file in&lt;br&gt;
&lt;a href="https://github.com/alievdavlat/translate-shield" rel="noopener noreferrer"&gt;the repo&lt;/a&gt;, produced by a Playwright spec you can&lt;br&gt;
re-run. Including the two I had to correct.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
