Figma में UI text एक design artifact है। यह mockup copy है, अक्सर product managers की बजाय designers द्वारा लिखी जाती है, शायद ही कभी i18n के लिए reviewed होती है। figmascope फिर भी इसे extract करता है — क्योंकि placeholder copy को भी resource key चाहिए अगर आप ऐसा code generate कर रहे हैं जो eventually localize होगा, और extraction process वह जगह है जहां logic रहती है।
strings.json वह artifact है जो dot-notation resource IDs को literal string values से map करता है। यह post covers करता है कि keys कैसे generate होती हैं, क्या filter out होता है, keys collide होने पर क्या होता है, और यह Android strings.xml और अन्य i18n formats से कैसे map होता है।
Format
{
"speed.test": "Speed Test",
"data.transfer.rate": "Data Transfer Rate",
"start": "Start",
"results.download": "Download",
"results.upload": "Upload",
"results.ping": "Ping",
"unit.mbps": "Mbps",
"settings.server.auto": "Auto Select"
}
Structure dot-notation resource IDs द्वारा keyed एक flat object है। Values Figma से literal string content हैं। Nested dot paths semantically meaningful हैं — results.download और results.upload same logical group में हैं — लेकिन file flat JSON है, nested नहीं। यह Android के strings.xml के काम करने के तरीके (grouping के लिए dot convention के साथ flat resource names) और अधिकांश i18n libraries (i18next, Rosetta, आदि) के flat key namespacing handle करने के तरीके से मेल खाता है।
Keys कैसे generate होती हैं
Key generation node की Figma layer name से शुरू होती है, text content से नहीं। "Data Transfer Rate" content के साथ Data Transfer Rate Label नाम का text node layer name से key generate करता है, value से नहीं।
Generation pipeline:
- Layer name लें
sanitizeNamefilters strip करें: Cyrillic characters transliterate करें, bidirectional/control characters (Unicode range U+202A–U+202E और similar) remove करें, non-alphanumeric non-space characters remove करें- Lowercase करें और spaces को dots से replace करें
- Leading और trailing dots trim करें
तो "Data Transfer Rate Label" → "data.transfer.rate.label"। Practice में, designers अक्सर trailing noun के बिना text layers name करते हैं, तो "Data Transfer Rate" → "data.transfer.rate"।
Cyrillic transliteration step exist करता है क्योंकि figmascope कई भाषाओं में Figma files के साथ use होता है। Скорость नाम की layer Skorost' transliterate होती है, फिर "skorost'" → special char strip के बाद → "skorost" बन जाती है। Pretty नहीं, लेकिन key same layer name के लिए runs में stable है।
Key generation layer name से होती है, text value से नहीं। Same text content लेकिन different layer names वाले दो text nodes अलग-अलग keys पाते हैं। Different text content लेकिन same layer name वाले दो text nodes collision create करते हैं — नीचे handle किया गया।
Key filters — क्या drop होता है
Figma file में हर text node localizable string नहीं होनी चाहिए। figmascope keys generate करने से पहले filter करता है:
- Empty strings: कोई content नहीं या whitespace-only content वाले Text nodes drop होते हैं।
- Numeric-only strings:
"42","100%","3.14"जैसी values drop होती हैं। ये data values हैं, UI copy नहीं, और आपके data layer से आनी चाहिए। - Short strings (≤2 characters): Single characters और two-character strings drop होती हैं। Icons, bullet points, superscripts — ये string resources नहीं हैं।
- Keys जो empty sanitize हो जाती हैं: अगर layer name में केवल ऐसे characters हैं जो
sanitizeNameद्वारा stripped होते हैं, तो result empty key है। ये nodes silently drop होते हैं।
Numeric filter को अधिक explanation चाहिए। Design mock में अक्सर placeholder numbers होते हैं: "42 ms" (ping), "150 Mbps" (download speed)। "42 ms" filter pass करता है क्योंकि यह purely numeric नहीं है — यह key "42.ms" बन जाएगी। लेकिन आप शायद बस "ms" को unit label के रूप में extract करना चाहेंगे और runtime पर 42 compute करना चाहेंगे। figmascope वह inference नहीं करता — यह full text as-is लेता है।
Collision handling
Collision तब होती है जब दो अलग-अलग text nodes same key produce करते हैं लेकिन different values होती हैं। उदाहरण के लिए: screen A पर "Label" नाम की layer में "Download" है और screen B पर "Label" नाम की layer में "Upload" है। दोनों key "label" generate करते हैं।
figmascope का collision rule: key को strings.json से पूरी तरह drop करें और _meta.json में warning emit करें:
// _meta.json
{
"warnings": [
"strings-collision:label"
]
}
Arbitrarily एक को रखना गलत होगा — आप silently दो strings में से एक को incorrectly translate करेंगे। Disambiguated keys (जैसे "label.1", "label.2") के साथ दोनों रखना एक guess होगी। Drop करना honest है।
IR collision को cleanly handle करता है: जब collision के कारण key drop होती है, figmascope IR में walk करता है और उसे reference करने वाले सभी leaf nodes से stringRef field remove करता है। text field (literal value) remain करती है। Agent एक leaf देखता है जिसमें text है लेकिन stringRef नहीं है और जानता है कि literal को fallback के रूप में use करना है।
// Collision resolution से पहले — same key, different text के साथ दो leaves
{ "kind": "leaf", "text": "Download", "stringRef": "label" }
{ "kind": "leaf", "text": "Upload", "stringRef": "label" }
// Collision resolution के बाद — key dropped, text preserved
{ "kind": "leaf", "text": "Download" }
{ "kind": "leaf", "text": "Upload" }
Warning आपको Figma में layer names fix करने के लिए कहती है। "Download Label" और "Upload Label" नाम की layers distinct keys "download.label" और "upload.label" produce करेंगी बिना collision के।
Android strings.xml पर mapping
Android strings.xml underscores के साथ flat string resource IDs use करता है। figmascope से dot-notation cleanly map होता है:
// strings.json
{
"speed.test": "Speed Test",
"data.transfer.rate": "Data Transfer Rate",
"results.download": "Download"
}
// → strings.xml (generated)
<resources>
<string name="speed_test">Speed Test</string>
<string name="data_transfer_rate">Data Transfer Rate</string>
<string name="results_download">Download</string>
</resources>
Transformation है: dots को underscores से replace करें। यह complete transform है। Android resource IDs dots allow नहीं करते; underscores conventional separator हैं। strings.json में key speed.test Kotlin में R.string.speed_test बन जाती है, जो कि CONTEXT.md constraint agent को point करती है जब वह stringRef: "speed.test" देखता है।
// CONTEXT.md constraint in action
// IR leaf: { "text": "Speed Test", "stringRef": "speed.test" }
// Agent output:
Text(text = stringResource(R.string.speed_test))
अन्य i18n formats पर mapping
Dot-notation i18n के लिए एक lingua franca है। अधिकांश systems इसे directly accept करते हैं या केवल minimal transformation चाहिए:
| Format | Key format | Dot-notation से transform |
|---|---|---|
| Android strings.xml | speed_test |
. को _ से replace करें |
| iOS Localizable.strings | "speed.test" |
None (dot-notation directly used) |
| i18next (JSON) | Nested: { "speed": { "test": "..." } } |
Flat keys को nested structure में expand करें |
| Flutter ARB | speedTest |
camelCase में convert करें |
figmascope dot-notation format output करता है। Target-specific transformation downstream handle होती है — या agent द्वारा (अगर CONTEXT.md target काफी explicit है) या एक small conversion script द्वारा।
strings.json क्या solve नहीं करता
Honest scope note: strings.json export time पर Figma में जो भी text exist करता है उससे extracted है। यह validated i18n resource file नहीं है। तीन problems जो आपको encounter होंगी:
Placeholder text: Figma mocks frequently Lorem Ipsum, "[Title Here]", या designer-authored copy use करते हैं जिसे review नहीं किया गया। Extracted strings वही हैं जो file में हैं, reviewed हों या नहीं।
Dynamic content: Designs अक्सर representative data के रूप में "John Doe" या "42 Mbps" दिखाते हैं। ये localizable strings नहीं हैं — ये template values हैं। figmascope design-time data और design-time copy के बीच distinguish नहीं कर सकता।
Filtered nodes से missing strings: अगर कोई text node filter fail करता है (too short, numeric-only, sanitization के बाद empty), तो वह strings.json में appear नहीं होगा और IR leaf में stringRef नहीं होगी। यह intentional है लेकिन इसका मतलब है कि आपकी string coverage Figma में layer naming की quality पर depend करती है।
Output एक starting point है। इसे अपनी i18n file में copy करें, अपनी actual resource naming conventions के against review करें, placeholder strings delete करें, और dynamic content keys manually add करें। यह Figma से manually हर text node extract करने की बजाय दस मिनट का काम है।
इस बारे में full picture के लिए कि stringRef IR से generated code में कैसे flow होता है, Per-Screen IR — Stack, Overlay, Absolute, Leaf देखें। String usage को govern करने वाले constraints के बारे में, CONTEXT.md की संरचना देखें।