<?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: Antony Hopkins</title>
    <description>The latest articles on DEV Community by Antony Hopkins (@figmat).</description>
    <link>https://dev.to/figmat</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%2F4110318%2Ffb5b5da8-e6a9-4e1e-bce5-331c454fa98c.png</url>
      <title>DEV Community: Antony Hopkins</title>
      <link>https://dev.to/figmat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/figmat"/>
    <language>en</language>
    <item>
      <title>Designing Plural-Safe Text in Figma</title>
      <dc:creator>Antony Hopkins</dc:creator>
      <pubDate>Sat, 05 Sep 2026 10:58:46 +0000</pubDate>
      <link>https://dev.to/figmat/designing-plural-safe-text-in-figma-232e</link>
      <guid>https://dev.to/figmat/designing-plural-safe-text-in-figma-232e</guid>
      <description>&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%2Fwx4y0wjtupez1b2gblqm.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%2Fwx4y0wjtupez1b2gblqm.png" alt="Correct vs incorrect Polish plural form for " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A translated Polish subscription screen ships. QA signed off. A user on the&lt;br&gt;
3-month plan sees "Otrzymaj 3 miesięcy dostępu Premium" — and it reads&lt;br&gt;
wrong, the way "3 childs" would in English. Grammatically, it should be&lt;br&gt;
"Otrzymaj 3 miesiące dostępu Premium." Same English source, same intended&lt;br&gt;
meaning, one wrong word.&lt;/p&gt;

&lt;p&gt;This is a pluralization bug, and it's a genuinely old, well-studied problem&lt;br&gt;
— not something this post is claiming to have discovered. Android has had&lt;br&gt;
quantity strings for over a decade. iOS has &lt;code&gt;.stringsdict&lt;/code&gt;. ICU&lt;br&gt;
MessageFormat and i18next both handle plural categories natively. Several&lt;br&gt;
localization platforms and design-tool plugins already offer some form of&lt;br&gt;
plural-aware preview or resource management. None of that is new.&lt;/p&gt;

&lt;p&gt;What this post walks through is narrower and more practical: how to catch&lt;br&gt;
this specific bug at the point where the text is actually designed, using&lt;br&gt;
&lt;a href="https://www.figma.com/community/plugin/880826733808822304/translations-for-figma-localization-toolbox" rel="noopener noreferrer"&gt;Translations for Figma&lt;/a&gt;'s Variant inspector — and, along the way, why the&lt;br&gt;
"obvious" fix (translate the existing resource file entry by entry) doesn't&lt;br&gt;
actually work, even though a lot of real localization work still does&lt;br&gt;
exactly that.&lt;/p&gt;
&lt;h2&gt;
  
  
  A quick primer: what's a "plural form," really?
&lt;/h2&gt;

&lt;p&gt;If you've only ever shipped an English-only product, this might be new to&lt;br&gt;
you, and that's fine — it's worth thirty seconds to get straight before&lt;br&gt;
anything else here makes sense.&lt;/p&gt;

&lt;p&gt;English plurals are deceptively simple: one item, or "other." "1 month" /&lt;br&gt;
"2 months." Two forms, always. It's easy to assume every language works the&lt;br&gt;
same way — translate the word, ship it.&lt;/p&gt;

&lt;p&gt;It doesn't. The Unicode CLDR plural rules define up to six grammatical&lt;br&gt;
categories per language (&lt;code&gt;zero&lt;/code&gt;, &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;two&lt;/code&gt;, &lt;code&gt;few&lt;/code&gt;, &lt;code&gt;many&lt;/code&gt;, &lt;code&gt;other&lt;/code&gt;), and&lt;br&gt;
which ones a language actually uses varies:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Plural categories for whole numbers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;English&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;one&lt;/code&gt;, &lt;code&gt;other&lt;/code&gt; (2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polish&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;one&lt;/code&gt;, &lt;code&gt;few&lt;/code&gt;, &lt;code&gt;many&lt;/code&gt; (3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arabic&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;zero&lt;/code&gt;, &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;two&lt;/code&gt;, &lt;code&gt;few&lt;/code&gt;, &lt;code&gt;many&lt;/code&gt;, &lt;code&gt;other&lt;/code&gt; (6)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One wrinkle worth flagging now so it doesn't look like a contradiction&lt;br&gt;
later: "categories a language's grammar actually distinguishes" and&lt;br&gt;
"entries a resource file needs" aren't quite the same count. Android and&lt;br&gt;
iOS both treat &lt;code&gt;other&lt;/code&gt; as a mandatory fallback bucket regardless of&lt;br&gt;
language, so even Polish's resource ends up with a fourth &lt;code&gt;other&lt;/code&gt; entry&lt;br&gt;
alongside its three real ones — more on that when it comes up.&lt;/p&gt;

&lt;p&gt;Both Android and iOS resource formats already know about this — a&lt;br&gt;
&lt;code&gt;&amp;lt;plurals&amp;gt;&lt;/code&gt; block in Android or a &lt;code&gt;.stringsdict&lt;/code&gt; entry in iOS is &lt;em&gt;built&lt;/em&gt; to&lt;br&gt;
hold one string per category, and the OS picks the right one at runtime&lt;br&gt;
based on the actual count and the device's locale. So the file format isn't&lt;br&gt;
the problem. Filling it in correctly is.&lt;/p&gt;
&lt;h2&gt;
  
  
  The mistake that ships anyway: translating a resource file literally
&lt;/h2&gt;

&lt;p&gt;Here's where a lot of real-world localization goes wrong, and it's worth&lt;br&gt;
being blunt about it: &lt;strong&gt;translating a plural resource entry by entry, the&lt;br&gt;
way you'd translate a normal string, is fundamentally incorrect&lt;/strong&gt; — and&lt;br&gt;
some translators, translation tools, and even careless engineers still do&lt;br&gt;
exactly that.&lt;/p&gt;

&lt;p&gt;Take the English source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Android: strings.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plurals&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"premium_access_months"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Get %d month of Premium access&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"other"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Get %d months of Premium access&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plurals&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two entries: &lt;code&gt;one&lt;/code&gt;, &lt;code&gt;other&lt;/code&gt;. A literal, entry-by-entry translation into&lt;br&gt;
Polish — translate what's there, keep the same structure — produces this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- WRONG: a literal, entry-by-entry translation --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plurals&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"premium_access_months"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesiąc dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"other"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesięcy dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plurals&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks reasonable if you don't already know Polish needs three&lt;br&gt;
categories, not two. But Polish's plural rule says a count like 3 resolves&lt;br&gt;
to &lt;code&gt;few&lt;/code&gt; — and this resource has no &lt;code&gt;few&lt;/code&gt; entry. Android's plural&lt;br&gt;
resolution doesn't error out when a category is missing; it silently falls&lt;br&gt;
back to &lt;code&gt;other&lt;/code&gt;. So for a count of 3, the app renders the &lt;code&gt;other&lt;/code&gt; string —&lt;br&gt;
"Otrzymaj 3 miesięcy dostępu Premium" — which is exactly the wrong,&lt;br&gt;
ungrammatical text from the top of this post. The bug isn't a typo. It's a&lt;br&gt;
direct, mechanical consequence of translating the file the way you'd&lt;br&gt;
translate any other string, instead of re-deriving the &lt;em&gt;entire category&lt;br&gt;
set&lt;/em&gt; for the target language.&lt;/p&gt;

&lt;p&gt;A correct Polish version needs entries the English source never had anything&lt;br&gt;
to translate &lt;em&gt;from&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Android: strings.xml (Polish) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plurals&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"premium_access_months"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesiąc dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"few"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesiące dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"many"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesięcy dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"other"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesięcy dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plurals&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four entries, not two — even though Polish grammar only ever &lt;em&gt;selects&lt;/em&gt;&lt;br&gt;
&lt;code&gt;one&lt;/code&gt;, &lt;code&gt;few&lt;/code&gt;, or &lt;code&gt;many&lt;/code&gt; for a whole-number count. &lt;code&gt;other&lt;/code&gt; is included&lt;br&gt;
anyway because Android treats it as the one mandatory fallback bucket every&lt;br&gt;
locale falls back to, regardless of what that language's own grammar needs;&lt;br&gt;
for an integer-only count like this it'll realistically never be chosen at&lt;br&gt;
runtime, so it's given the same text as &lt;code&gt;many&lt;/code&gt;. Leaving it out is exactly&lt;br&gt;
the kind of gap that looks harmless until an edge case nothing anticipated&lt;br&gt;
hits it.&lt;/p&gt;

&lt;p&gt;Keep this in mind — it's exactly what the walkthrough below produces.&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%2Ftzto4m1ey3m1ljym3h0a.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%2Ftzto4m1ey3m1ljym3h0a.png" alt="big picture on Correct vs incorrect Polish plural form" width="797" height="118"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Where this is easiest to catch: at design time
&lt;/h2&gt;

&lt;p&gt;Nobody writing the Figma design ever sees any of this. A text layer holds&lt;br&gt;
one static string. Nobody notices that Polish "miesięcy" is visibly longer&lt;br&gt;
than English "months," or that a short &lt;code&gt;one&lt;/code&gt; form leaves a button looking&lt;br&gt;
oddly empty, until a real build, on a real device, with a real count,&lt;br&gt;
finally exposes it — usually well after the design was signed off, and&lt;br&gt;
usually to whoever's translating or QA-ing the build, not the person who&lt;br&gt;
designed the screen.&lt;/p&gt;

&lt;p&gt;The rest of this post is a walkthrough of doing two things — checking the&lt;br&gt;
layout, and generating the actual resource — from the same place and the&lt;br&gt;
same data, using the Variant inspector in Translations for Figma.&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%2F0x44hduvwzb2f30ysz3y.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%2F0x44hduvwzb2f30ysz3y.png" alt="a plain Figma frame with a single&lt;br&gt;
text layer selected, reading " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: add samples to preview the layout
&lt;/h2&gt;

&lt;p&gt;Select the text layer and open the Variant inspector. Add a few&lt;br&gt;
&lt;strong&gt;samples&lt;/strong&gt; — plain, realistic alternate values the count could actually&lt;br&gt;
take:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Get 1 month of Premium access"&lt;/li&gt;
&lt;li&gt;"Get 3 months of Premium access"&lt;/li&gt;
&lt;li&gt;"Get 12 months of Premium access"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(1/3/12 happen to land on Polish's &lt;code&gt;one&lt;/code&gt;/&lt;code&gt;few&lt;/code&gt;/&lt;code&gt;many&lt;/code&gt; categories too —&lt;br&gt;
convenient for this walkthrough, though at this stage a sample is still&lt;br&gt;
just plain text, added to stress-test the layout, nothing more.)&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%2Fgv1mj8xylpuygth428sn.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%2Fgv1mj8xylpuygth428sn.png" alt="the Variant inspector panel open on this text layer, with the three&lt;br&gt;
samples listed (1 month, 3 months, 12 months), one of them selected/&lt;br&gt;
highlighted, and the Figma canvas behind/beside it showing the layout with&lt;br&gt;
that sample's text rendered live — demonstrating instant on-canvas preview&lt;br&gt;
per sample." width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click through the samples on canvas. This immediately shows whether the&lt;br&gt;
layout survives the range — a short "1 month" button next to a much wider&lt;br&gt;
"12 months" one, say. This is the layout half of the problem, solved,&lt;br&gt;
before a single line of code exists.&lt;/p&gt;

&lt;p&gt;One aside, since it's easy to conflate: samples aren't &lt;em&gt;only&lt;/em&gt; for plural&lt;br&gt;
counts. The same mechanism also covers a text layer whose content varies&lt;br&gt;
for unrelated reasons — a shared button showing "Next," "Continue," or "Add&lt;br&gt;
to cart" depending on which screen it's on. That's a real, separate use of&lt;br&gt;
samples, but it's out of scope for this post; here, every sample on this&lt;br&gt;
layer is the same sentence with a different count.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: generate the resource pattern, don't hand-author it
&lt;/h2&gt;

&lt;p&gt;Samples aren't just for the visual check — they're also what the plugin&lt;br&gt;
uses to derive the actual resource entry, so nobody has to separately&lt;br&gt;
author the plural rule by hand.&lt;/p&gt;

&lt;p&gt;The Variant inspector has an &lt;strong&gt;"Add pattern"&lt;/strong&gt; button for typing an entry&lt;br&gt;
from scratch, and an &lt;strong&gt;"✨ AI generate"&lt;/strong&gt; button that derives the pattern&lt;br&gt;
automatically from the samples already on the layer. Pick your target&lt;br&gt;
platform (iOS, Android, or both) and a resource id — auto-generated from&lt;br&gt;
the text and kept in sync with it, becoming the exact key your app's code&lt;br&gt;
will reference.&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%2Ff5bs3mu4fj93s02exkj0.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%2Ff5bs3mu4fj93s02exkj0.png" alt="after clicking " width="800" height="301"&gt;&lt;/a&gt;
are visible (one and other)"/&amp;gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;AI generate&lt;/strong&gt;. For English, this produces exactly the two-entry&lt;br&gt;
pattern shown earlier — &lt;code&gt;one&lt;/code&gt;/&lt;code&gt;other&lt;/code&gt; — because that's all English's&lt;br&gt;
grammar needs. Unremarkable on its own. The interesting part happens once&lt;br&gt;
you translate.&lt;/p&gt;

&lt;p&gt;A quick note on cost, since it's easy to gloss over in a post like this and&lt;br&gt;
get called out for it later: a pattern can always be typed by hand in a&lt;br&gt;
plain text field — that stays free, and isn't going anywhere. "AI generate"&lt;br&gt;
currently calls out to the plugin's own backend and isn't separately&lt;br&gt;
charged for today. If that ever changes, manual authoring remains the&lt;br&gt;
baseline either way; AI generation is a convenience layer on top of a&lt;br&gt;
workflow that still works without it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: translate the interface, then generate the target pattern
&lt;/h2&gt;

&lt;p&gt;Using the plugin menu, translate the interface into Polish. Reopen the&lt;br&gt;
Variant inspector on the same layer. Its &lt;strong&gt;samples are already&lt;br&gt;
translated&lt;/strong&gt; — translation applies to samples the same as any other text&lt;br&gt;
in the plugin — but the &lt;strong&gt;pattern is not&lt;/strong&gt;. Patterns don't auto-translate,&lt;br&gt;
because a plural resource entry isn't a translation of a sentence, it's a&lt;br&gt;
distinct grammatical artifact that has to be derived for the target&lt;br&gt;
language specifically.&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%2F8knnj52wchpgqpknho7p.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%2F8knnj52wchpgqpknho7p.png" alt="samples are already translated, but the patterns section for Polish is empty" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's also a &lt;strong&gt;"Copy source + translate"&lt;/strong&gt; button here, and it's worth&lt;br&gt;
pausing on exactly what it does: it machine-translates each existing source&lt;br&gt;
entry, one at a time, keeping the same entries the source had. That's&lt;br&gt;
useful for a pattern that genuinely doesn't need restructuring — but for a&lt;br&gt;
plural pattern going from English (&lt;code&gt;one&lt;/code&gt;/&lt;code&gt;other&lt;/code&gt;) to Polish (&lt;code&gt;one&lt;/code&gt;/&lt;code&gt;few&lt;/code&gt;/&lt;br&gt;
&lt;code&gt;many&lt;/code&gt;, plus the mandatory &lt;code&gt;other&lt;/code&gt; fallback), it reproduces precisely the&lt;br&gt;
"literal translation" mistake from earlier in this post: two entries in,&lt;br&gt;
two entries out, &lt;code&gt;few&lt;/code&gt; and &lt;code&gt;many&lt;/code&gt; both missing. It's the right tool for&lt;br&gt;
some jobs and the wrong one for this one.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;AI generate&lt;/strong&gt; instead. It doesn't copy or translate the existing&lt;br&gt;
entries — it derives a fresh pattern for Polish, from the samples, using&lt;br&gt;
Polish's own plural rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Android: strings.xml (Polish) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plurals&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"premium_access_months"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"one"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesiąc dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"few"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesiące dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"many"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesięcy dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;item&lt;/span&gt; &lt;span class="na"&gt;quantity=&lt;/span&gt;&lt;span class="s"&gt;"other"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Otrzymaj %d miesięcy dostępu Premium&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plurals&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four entries, correctly — &lt;code&gt;one&lt;/code&gt;/&lt;code&gt;few&lt;/code&gt;/&lt;code&gt;many&lt;/code&gt; because that's what Polish&lt;br&gt;
grammar actually distinguishes for a whole-number count, plus &lt;code&gt;other&lt;/code&gt; as&lt;br&gt;
the mandatory fallback the resource format itself requires — not because&lt;br&gt;
anyone copied, translated, or hand-fixed the English version. Switch&lt;br&gt;
platforms to check iOS's &lt;code&gt;.stringsdict&lt;/code&gt; shape too; same categories,&lt;br&gt;
different format.&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%2F2pfsnmt36wnrcql64xuq.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%2F2pfsnmt36wnrcql64xuq.png" alt="Polish target language, with all four &lt;item&gt; entries" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: compare source and target, then export
&lt;/h2&gt;

&lt;p&gt;The Variant inspector's own language switch lets you flip between the&lt;br&gt;
source language's samples/patterns and the target's, right inside the same&lt;br&gt;
panel — a quick way to visually compare the two without leaving the&lt;br&gt;
inspector.&lt;/p&gt;

&lt;p&gt;When you're done, open &lt;strong&gt;Plugins → Translations for Figma → Tools →&lt;br&gt;
Resources&lt;/strong&gt; and download the generated files for each target platform —&lt;br&gt;
real Android &lt;code&gt;strings.xml&lt;/code&gt;/&lt;code&gt;&amp;lt;plurals&amp;gt;&lt;/code&gt; and iOS &lt;code&gt;.strings&lt;/code&gt;/&lt;code&gt;.stringsdict&lt;/code&gt;&lt;br&gt;
output, plural rules already resolved, ready to hand to engineering.&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%2F0ek6ypydfcfa5hhurwji.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%2F0ek6ypydfcfa5hhurwji.png" alt="Resources panel, listing downloadable resource files&lt;br&gt;
per language/platform" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother, if this is a solved problem?
&lt;/h2&gt;

&lt;p&gt;To be fair to the question: pluralization itself isn't solved &lt;em&gt;here&lt;/em&gt; for&lt;br&gt;
the first time, and this post isn't pretending otherwise. What changes is&lt;br&gt;
where it happens. The layout check and the resource generation both run&lt;br&gt;
from data (samples) a designer was already going to create to test the&lt;br&gt;
screen, in the same tool the screen was designed in, without a separate&lt;br&gt;
localization engineer, a separate platform account, or a round trip back&lt;br&gt;
to whoever designed the screen once a bug like the cover image's finally&lt;br&gt;
gets noticed. For a small team without dedicated localization tooling&lt;br&gt;
already in place, that's mostly a matter of saved time and one fewer place&lt;br&gt;
for the mistake from earlier in this post to sneak back in — not a new&lt;br&gt;
capability nobody's ever had.&lt;/p&gt;

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

&lt;p&gt;The plugin is &lt;a href="https://www.figma.com/community/plugin/880826733808822304/translations-for-figma-localization-toolbox" rel="noopener noreferrer"&gt;Translations for Figma&lt;/a&gt;&lt;br&gt;
on the Figma Community, free tier included. If you've run into a shipped&lt;br&gt;
plural bug like this one, we'd genuinely like to hear how it got caught (or&lt;br&gt;
didn't) — comment below.&lt;/p&gt;

</description>
      <category>figma</category>
      <category>android</category>
      <category>ios</category>
      <category>i18n</category>
    </item>
  </channel>
</rss>
