Paprašėte Claude Code pridėti prisijungimo formos įkėlimo būseną. Įkėlimo būsena veikia. Tačiau mygtuke dabar parašyta „Prisijungti“, o ne „Prisijungti prie paskyros“, klaidos pranešimas tapo draugiškesnis, o viena antraštė staiga parašyta sakinio registru. Niekas to neprašė, visi testai praeina, ir jei kas nors neperskaito viso skirtumo eilutė po eilutės, pakeitimas patenka į leidimą.

Šis įrašas apie konkrečią nesėkmę: esamą, patvirtintą tekstą AI programavimo agentas tyliai perrašo, ir apie procesą, kuris tam užkerta kelią. Eilutės, kurias agentai sukuria įrašydami tiesiai į kodą ir nesusiedami su raktais, yra kita problema — ji aptariama straipsnyje kodėl AI programavimo įrankiai nuolat prideda tekstą tiesiai į kodą. Kur apskritai turėtų būti laikomi produkto tekstai, yra architektūros klausimas, aptariamas straipsnyje kodui pritaikyti produkto tekstai. Šiame įraše nagrinėjamas tik incidentas — pirmadienio rytas, kai tekstas pasikeitė, nors niekas nenusprendė, kad taip turi būti. globalize.now — kodui pritaikyta tekstų valdymo sistema su integruotu lokalizavimu, ir šis incidentas yra viena iš priežasčių, kodėl ji sukurta.

Kodėl AI programavimo agentai perrašo sąsajos tekstus?

AI programavimo agentai perrašo sąsajos tekstus, nes mato paprastą tekstą komponentuose. Kai šis tekstas laikomas už raktų šaltinio lokalės faile, jo keitimas tampa aiškiu, peržiūrimu pakeitimu, o ne šalutiniu kitos užduoties poveikiu.

Komponente „Prisijungti“ neturi jokio ypatingo statuso. Tai eilutės literalas JSX atribute, niekuo nesiskiriantis nuo className ar testo identifikatoriaus. Agentas buvo mokytas remiantis milijonais skirtumų, kuriuose šalia esančio kodo tobulinimas buvo laikomas geru elgesiu, o modeliui etiketės padarymas „aiškesne“ yra toks pats veiksmas kaip kintamojo pervadinimas. Nėra nei laukiančios tipo klaidos, nei nepraeinančio testo, nei atsakingo asmens žymos prie tų žodžių. Agentui perrašyti tekstą nieko nekainuoja.

Pakeitimas peržiūrą praeina dėl tos pačios priežasties. Peržiūrintys žmonės skaito logiką. Teksto pakeitimas atsiduria skirtumo viduryje, nors skirtumas iš tiesų susijęs su įkėlimo būsena; kodas kompiliuojamas, sąsaja atvaizduojama, o jei snapshot testas praneša apie problemą, įprasta reakcija — atnaujinti snapshot, kuris naują tekstą užfiksuoja taip, tarsi jis būtų patvirtintas.

Ar taisyklių failai, pavyzdžiui, AGENTS.md, iš tikrųjų tai sustabdo?

Agentų taisyklių failai sumažina dažnį, bet nepadaro sąsajos tekstų neįmanomų redaguoti. Redaguojamą pakeitimą matomą padaro architektūra.

Taisyklių failą vis tiek turėkite — tai pigiausias sluoksnis, kuris veikia pakankamai dažnai, kad būtų vertas trisdešimties sekundžių. Šis blokas veikia AGENTS.md, CLAUDE.md ir Cursor taisyklėse (.cursorrules arba .cursor/rules/):

## UI copy policy — do not modify user-facing text

- Never change user-visible strings (button labels, headings, empty states,
  error messages, tooltips, placeholder text) unless the task explicitly
  asks for a copy change.
- User-visible text lives in the source locale file (e.g. locales/en.json).
  Reference it by key. Never inline a new user-facing string in a component.
- If a task needs new user-facing text, add a key to the source locale file,
  reference it, and list the new key in your summary for copy review.
- Any diff to the source locale file is a copy change. Call it out
  separately — it needs its own approval, apart from code review.

Dabar — atvirai. Taisyklė yra kontekstas, o kontekstas konkuruoja. Atliekant ilgą užduotį ši instrukcija tėra viena eilutė tarp tūkstančių kodo žetonų, todėl kartais pralaimi — dėl konteksto sutraukimo, dėl pagalbinio agento, kuris jos niekada nematė, arba dėl stipraus šablono aplinkiniame faile. Dar blogiau — taisyklę pažeidęs agentas apie tai nepraneša. Negaunate pranešimo, kad tekstas pasikeitė; gaunate skirtumą, kuriame jis tiesiog būna pasikeitęs. Susitarimas nėra patikra.

Taigi taisyklių failas yra pirmasis sluoksnis, tačiau vien juo pasitikėti nereikėtų.

Kaip padaryti, kad teksto pakeitimas būtų matomas, o ne tylus?

Perkelkite kiekvieną naudotojui matomą eilutę iš komponentų ir laikykite ją už raktų šaltinio lokalės faile. Tuomet agentas, norintis pakeisti jūsų tekstą, turės redaguoti failą, kurio visa paskirtis — tekstas.

Tai žingsnis, kurio taisyklių failas atlikti negali, o mechanizmas paprastas. Kai komponentai nurodo t('auth.signIn'), o ne iš naujo įrašo „Prisijungti“, vienu metu pasikeičia du dalykai. Komponentų skirtumuose nebelieka tekstų, todėl agentas, dirbantis su įkėlimo būsena, neturi kur perrašyti teksto. Be to, kiekvienas teksto pakeitimas — agento ar žmogaus — patenka į vieną failą, kuriame pakeista eilutė yra jums svarbus įvykis, o ne triukšmas aplink jį. Lokalės failo skirtumą galima patikrinti per kelias sekundes. Netinkamą perrašymą galima atšaukti pakeitus vieną eilutę.

Tiksliau tariant, ką tai suteikia: agentas vis tiek gali redaguoti lokalės failą. Esmė ne ta, kad žodžiai tampa neliečiami — esmė ta, kad jų palietimas nustoja būti šalutiniu poveikiu ir tampa aiškiu, peržiūrimu veiksmu. Tai skirtumas tarp to, ar apie pakeitimą sužinote iš skirtumo, ar iš kliento.

Išsamus argumentas, kodėl tiesos šaltinį verta laikyti kodų bazėje, o ne su ja sinchronizuojamame dizaino įrankyje, pateiktas straipsnyje kodui pritaikyti produkto tekstai. Šiam įrašui svarbi tik viena pasekmė: tekstai su raktais taisyklių failo prašymą paverčia patikrinamu dalyku.

Kaip atrodo peržiūros vartai?

Kiekvieną šaltinio lokalės failo skirtumą laikykite teksto pakeitimu ir nukreipkite jį asmeniui, atsakingam už tekstus.

Praktiškai: įtraukite lokalės katalogą į CODEOWNERS, kad kiekvienam jo pakeitimui būtų paprašyta tekstus prižiūrinčio žmogaus peržiūros. Į PR šabloną įrašykite vieną eilutę — „Ar šis PR keičia naudotojui matomą tekstą ir ar tai buvo užduotis?“. Taip pat palikite taisyklių faile reikalavimą, kad agentas santraukoje išvardytų pakeistus raktus. Kai jis to laikosi, peržiūra tampa momentinė, o kai ne — CODEOWNERS mechanizmas vis tiek tai užfiksuoja.

Mažai komandai tai lengviau, nei skamba. Lokalės skirtumas trumpas, parašytas paprasta kalba, o klausimas „Ar dabar šiame mygtuke turėtų būti „Prisijungti“?“ yra sprendimas, kurį galima priimti per penkias sekundes — jei tik klausimas iš tiesų pateikiamas atsakingam žmogui. Būtent tai ir yra vartų paskirtis.

Ką daryti, jei agentas jau perrašė jūsų tekstą?

Pirmiausia atkurkite patvirtintą tekstą, tada susiekite eilutes su raktais, kad kitas perrašymas būtų matomas skirtume.

Žalos paieška yra git užduotis: palyginkite paveiktus komponentus su paskutiniu patikimu commit ir perskaitykite tik eilučių literalus. Atkurkite tai, kas pasikeitė. Jei negalite užtikrintai pasakyti, kuris tekstas buvo patvirtintas — mygtuke parašyta „Prisijungti“, rinkodaros puslapyje „Prisijungti prie paskyros“, o joks artefaktas nefiksuoja, kuris variantas teisingas — susidūrėte su gilesne būsena, prie kurios prisideda šis incidentas. Teksto dreifas — tai naudotojui matomo teksto neatitikimas patvirtintam šaltiniui skirtinguose paviršiuose ir laikui bėgant, kai nėra vieno tiesos šaltinio, nuo kurio būtų galima nukrypti. Šiam terminui, jo priežastims ir pasekmėms skirtas atskiras straipsnis: kas yra teksto dreifas.

Tada susiekite su raktais tai, ką atkūrėte, pradėdami nuo eilučių, kurias palietė agentas. Akivaizdu, kad būtent jos yra pavojaus zonoje.

Kur čia įsiterpia lokalizavimas?

Tylus teksto perrašymas viena kalba yra nepatogumas, o dešimčia kalbų — rizika: kiekvienas vertimas, sukurtas pagal seną tekstą, dabar yra pasenęs, tačiau niekas neinformuoja, kad reikia versti iš naujo.

Čia agento incidentas dar labiau išplinta. Išleidžiate perrašytą anglišką tekstą, o vokiečių, japonų ir ispanų kalbomis vis dar rašoma sena versija — dabar kalbos nesutampa ne tik skirtinguose ekranuose, bet ir tarpusavyje. Katalogų išsiderinimas yra atskiras nesėkmės scenarijus, jo sprendimai aprašyti straipsnyje sinchronizaciją praradę vertimo failai.

Tekstai su raktais uždaro ir šį ciklą, nes pakeista šaltinio eilutė tampa matomu įvykiu, nuo kurio priklauso jos vertimai, o ne tyliai pajudėjusiu literalu. Tuo grindžiamas globalize.now: tekstai laikomi kodų bazėje, turi vieną šaltinį už raktų, o lokalizavimas yra ta pati operacija, o ne papildomai prijungtas sluoksnis — prijunkite saugyklą ir kiekviena kalba bus išvesta iš to vieno šaltinio. Komandos, leidžiančios produktus naudodamos AI programavimo įrankius, su tuo susiduria anksčiausiai, todėl rašome kūrėjams ir žmonėms, kuriantiems su AI įrankiais.

Kai kitą kartą agentas dirbs jūsų komponentuose, klausimas bus toks: ar pakeista etiketė pasirodys kaip sprendimas, ar kaip netikėtumas? globalize.now saugo naudotojui matomas eilutes kaip vieną šaltinį jūsų prijungtoje saugykloje ir iš to vieno teksto išveda kiekvieną kalbą.

globalize.now paverčia užkoduotą programos tekstą į vertimui paruoštus lokalės failus ir juos atnaujina, kai jūs diegiate naujus pakeitimus.

Išbandyti globalize.now nemokamai