10 erori comune de i18n și cum să le eviți
Aflați cele mai frecvente erori de internaționalizare pe care le fac dezvoltatorii și cum să le remediați. Îmbunătățiți calitatea localizării aplicației dvs. cu aceste practici de top.
Internaționalizarea (i18n) pare simplă — până descoperiți că utilizatorii dvs. germani văd butoane tăiate, utilizatorii japonezi primesc fragmente de propoziții rupte și utilizatorii vorbitori de arabă au layout-uri complet stricate. Nu sunt cazuri izolate. Sunt consecințele predictibile ale celor mai frecvente erori de i18n pe care echipele de dezvoltare le fac atunci când abordează localizarea pentru prima dată. În acest ghid vom aborda cele 10 erori i18n cele mai comune, vom explica exact de ce apar și vom arăta pas cu pas cum să corectezi fiecare. Indiferent dacă construiești o aplicație nouă sau actualizezi una existentă — evitarea acestor capcane te va ajuta să economisești săptămâni de depanare.
Eroare #1: Șiruri codificate
Șiruri de caractere codificate direct în cod sunt cea mai fundamentală eroare i18n. Se întâmplă pentru că dezvoltatorii se concentrează mai întâi pe a face funcționalitățile să funcționeze și planifică „să aranjeze mai târziu”. Dar mai târziu nu vine niciodată, iar brusc ai mii de șiruri distribuite prin sute de fișiere.
['Configurează cadrul i18n înainte de a scrie prima linie de cod UI', 'Folosește un plugin de lint pentru a detecta stringuri hardcodate în template-uri și componente', 'Păstrează cheile de traducere descriptive și organizate după funcționalitate sau pagină']
Configurați cadrul i18n înainte de a scrie prima linie de cod UI.
Folositi un plugin de lint pentru a detecta șiruri hardcodate în template-uri și componente.
Păstrați cheile de traducere descriptive și organizate după funcționalitate sau pagină.
Un scenariu tipic
Un dezvoltator scrie eticheta unui buton direct în JSX: <button>Submit Order</button>.
Aplicația este livrată în engleză și funcționează impecabil. Șase luni mai târziu, compania se extinde în Germania.
Echipa de localizare descoperă 2.000+ șiruri codificate. Intervenția durează 3 săptămâni și generează 47 de erori.
De ce este acesta o problemă
Într-o bază de coduri matură, șiruri hardcodate pot ajunge la mii. Îndepărtarea lor ulterioră necesită să atingăți fiecare fișier, să testați din nou fiecare componentă și să riscați regresii în tot sistemul.
Șiruri codificate direct în cod sursă, template-uri sau componente sunt încorporate. Nu pot fi extrase, traduse sau schimbate în timpul execuției fără a modifica codul în sine.
Utilizatorii din locale care nu sunt engleză văd elemente ale UI nem translate în amestec cu conținutul tradus — o impresie haotice și neprofesională.
Cum să rezolvi acest lucru
Mută toate șirurile vizibile utilizatorului de la început în fișierele de resurse.
Configurează un framework de traducere (de exemplu, next-intl, react-i18n, vue-i18n) înainte de a scrie primul tău component.
Creează o structură de fișiere de resurse (de exemplu, messages/de.json) și referențiați toate șirurile prin chei de traducere precum t('checkout.submitButton').
Adaugă o regulă de lint sau un hook de pre-commit care să marcheze literal string brut în componentele UI.
Eroarea nr. 10: Traducerea literală a totului.
Nu toate conținuturile ar trebui traduse. Numele de mărci, denumirile persoanelor juridice, termeni tehnici specifici și anumite denumiri de produse trebuie să rămână în limba lor originală. Traducerea excesivă poate provoca probleme legale, inconsistența mărcii și confuzie pentru utilizatori.
["Mențineți un glosar 'Nu se traduce' și împărțiți-l cu toți traducătorii", 'Folosiți segmente blocate sau namespace-uri separate pentru termeni de marcă și termeni juridici', 'Furnizați întotdeauna note de context pentru șiruri de caractere ambigue, pentru a preveni traducerile greșite']
Mențineți un glosar de „nu traduceți” și împărtășiți-l cu toți translatorii.
Folositi segmente blocate sau spații de nume separate pentru termeni de marcă și termeni legali.
Oferiți întotdeauna note de context pentru șiruri ambigu pentru a preveni traduceri greșite.
Un scenariu tipic
Un fișier de traducere conține numele companiei 'CloudForge Inc.' și termenul tehnic 'OAuth 2.0 Token' ca șiruri traduse obișnuite.
Traducătorul spaniol traduce 'CloudForge' ca 'ForjaNube' și 'OAuth 2.0 Token' ca 'token OAuth 2.0'.
Rezultat: utilizatorii nu găsesc compania după numele său real, iar dezvoltatorii care citesc documentația în spaniolă sunt confuzi de termeni tehnici traduşi într-un mod necunoscut.
De ce este aceasta o problemă
Un singur nume de marcă tradus încorect într-un document juridic poate invalida contracte. Corectarea acestuia necesită revizuirea fiecărui șir în fiecare limbă — un efort de mai multe săptămâni.
Dacă toate șirurile sunt trimise pentru traducere fără context, traducătorii pot traduce nume de mărci ('Apple' → 'Mașină'), termeni juridici ('GmbH' → 'LLC') sau termeni tehnici care trebuie să rămână în engleză.
Utilizatorii nu întâlnesc produsele după numele de marcă cunoscut, documentele juridice fac referire la compania greșită, iar documentația tehnică devine confuză atunci când termeni precum 'API Endpoint' sunt traduți.
Cum să rezolvi asta
Marcați conținutul care nu trebuie tradus în mod clar și furnizați note de context pentru traducători.
Creează un glosar 'Nu se traduce' care listează toate mărcile, denumirile de produse, persoanele juridice și termenii tehnici care trebuie să rămână nemodificați.
Folosește un spațiu de nume separat sau chei speciale pentru conținuturi care nu trebuie traduse. Multe instrumente i18n suportă segmente 'blocate' pe care traducătorii nu le pot edita.
Adaugă comentarii/descrieri pentru traducători în fișierele tale de traducere, explicând contextul: 'Acesta este un nume de marcă — nu se traduce' sau 'Termen tehnic — păstrează în engleză'.
Eroare #2: Concatenarea șirurilor
Îmbinarea propozițiilor din fragmente pare logică în engleză, dar nu funcționează în alte limbi. Ordinea cuvintelor, gramatica și construcția propozițiilor variază drastic între limbaje, ceea ce face imposibilă traducerea stringurilor îmbinate.
['Nu construi propoziții prin concatenarea fragmentelor traduse', 'Folosește înlocuitori numiți ('{name}') în loc de poziționali ({0}) pentru claritate', 'Oferă comentarii de context pentru traducători, explicând ce conține fiecare înlocuitor']
Nu construiți fraze prin concatenarea fragmentelor traduse.
Folosește înlocuitori numiți ('{name}') în loc de poziționali ({0}) pentru claritate
Oferiți comentarii de context pentru traducători, care să explice ce conține fiecare marcator de poziție.
Un scenariu tipic
Dezvoltatorul scrie: 'You have ' + count + ' items in your ' + cartType + ' cart' — funcționează perfect în limba engleză.
Traducătorul german primește trei fragmente separate și nu poate forma o propoziție din punct de vedere gramatical corect, deoarece ordinea cuvintelor trebuie să fie schimbată.
Rezultatul: Utilizatorii germani văd 'Sie haben 5 Artikel in Ihrem Warenkorb Standard' — neprofesional.
De ce este acesta o problemă
Fiecare șir conectat este o bombă cu ceas. Cu 20 de limbi și 50 de șiruri conectate, aveți 1.000 posibile erori gramaticale care trebuie corectate manual.
Concatenarea șirurilor de caractere, cum ar fi 'Bine ai venit ' + userName + ', ai ' + count + ' mesaje noi' presupune un anumit aranjament de cuvinte. Traducătorii primesc fragmente fără context, pe care nu îi pot reordona.
Utilizatorii văd propoziții din punct de vedere gramatical incorecte. În germană, verbul apare adesea la final. În arabă, întreaga structură este inversată. Rezultatul sună a nonsens.
Cum să-l rezolvi
Folosește mesaje parametrizate cu înlocuitori numiți, astfel încât traducătorii să poată să rearanjeze întreaga propoziție.
Înlocuiește concatenarea cu o cheie de mesaj unică cu înlocuitori: 'cart.summary': 'Ai {count} articole în coșul tău '{cartType}''.
Transmite variáveis ca parametri pentru funcția ta de traducere: t('cart.summary', { count: 5, cartType: 'Premium' }).
Traducătorii pot rearanja acum liber: 'În coșul tău '{cartType}' se află {count} articole' — în germană corect gramatical.
Eroare #3: Ignorarea pluralizării
Engleza are două forme de plural: singular și plural. Dezvoltatorii presupun adesea că toate limbile funcționează la fel. Nu funcționează. Poloneza are 4 forme, araba are 6, iar chiar și limbi precum franceza tratează zero diferit față de engleză.
['Utilize ICU MessageFormat sau o bibliotecă echivalentă pentru conținuturi contabile', 'Nu scrieți logică proprie de plural — încredeți-vă în regulile CLDR', 'Testați pluralul cu valori precum 0, 1, 2, 5, 21 și 100 pentru a acoperi toate categoriile']
Utilizați întotdeauna ICU MessageFormat sau o bibliotecă echivalentă pentru conținuturi cu pluralizare.
Nu scrieți niciodată o logică proprie de plural — încredeți-vă în regulile CLDR.
Testați formele de plural cu valori precum 0, 1, 2, 5, 21 și 100 pentru a acoperi toate categoriile.
Un scenariu tipic
Dezvoltatorul scrie: count + (count === 1 ? ' Datei' : ' Dateien') — gestionează corect limba germană.
Traducătorul polonez are nevoie de 4 forme: 1 plik, 2-4 pliki, 5-21 plików, 22-24 pliki. Operatorul ternar simplu nu poate exprima acest lucru.
Rezultatul: Utilizatorii polonezi văd '5 pliki' (formă incorectă) în loc de '5 plików' (formă corectă), iar aplicația pare a fi defectă.
De ce este aceasta o problemă
Fiecare substantiv numărabil din aplicația ta are nevoie de tratament pentru plural. Cu 50 de astfel de șiruri și 20 de limbi, sunt 1.000 de reguli de plural — imposibil de gestionat manual.
Verificări simple cu if/else (count === 1 ? 'Fișier' : 'Fișiere') tratează doar germană/engleză. CLDR definește până la 6 categorii de plural: zero, one, two, few, many și other. Fiecare limbă utilizează un subset diferit.
Utilizatorii văd texte din punct de vedere gramatical incorecte, cum ar fi '1 Nachrichten', sau forme de plural complet incorecte. În contexte formale, acest lucru compromite credibilitatea.
Cum să-l rezolvi
Folosește ICU MessageFormat, care acceptă din start toate regulile CLDR de plural.
Definește mesajele cu sintaxa ICU: 'fileCount': '{count, plural, one {# Fișier} other {# Fișiere}}'.
Traducătorii furnizează toate formele de plural necesare limbii lor. Poloneza: '{count, plural, one {# plik} few {# pliki} many {# plików} other {# pliku}}'.
Biblioteca ta i18n selectează automat, în timpul rulării, forma corectă pe baza regulilor CLDR ale localității active.
Eroare #4: Lățimi UI fixe
Designerii creează layouturi cu pixel-perfecțiune în engleză, iar dezvoltatorii le implementează cu lățimi fixe. Cu toate acestea, textul tradus poate fi semnificativ mai lung sau mai scurt. Textul în germană este aproximativ cu 30% mai lung decât engleza, în timp ce textul chinez poate fi cu aproximativ 50% mai scurt.
['Nu utilizați niciodată lățimi fixe în pixeli pentru elemente cu text tradus', 'Planificați pentru o creștere de 40% a textului ca linie de bază — unele limbi se extind mai mult', 'Folosiți CSS Flexbox sau Grid pentru layout-uri care se adaptează la lungimi variabile ale conținutului']
Nu utilizați lățimi fixe în pixeli pentru elemente cu text tradus.
Planificați un prag de 40% pentru extinderea textului ca linie de bază — unele limbi se extind și mai mult.
Folosiți CSS Flexbox sau Grid pentru layouturi care se adaptează la lungimi variabile ale conținutului.
Un scenariu tipic
Designerul creează o bară de navigare cu 5 butoane, fiecare având lățimea exactă de 100px — arată bine în engleză.
Traducerea germană: 'Settings' devine 'Setări' (13 caractere vs 8), 'Submit' devine 'Trimite' (6). Bara de navigare se depășește.
Rezultat: Pe dispozitivele mobile, butoanele se aliniază una peste alta sau textul este tăiat, ceea ce face ca navigarea să fie inutilă pentru utilizatorii germani.
De ce este o problemă
Fiecare element cu lățime fixă este un punct potențial de rupere. O aplicație tipică are sute de butoane, etichete și carduri care trebuie să suporte creșterea textului.
Containere cu lățime fixă (width: 120px) și butoane de dimensiune fixă se taie sau se depășesc când textul se extinde. overflow: hidden în CSS ascunde conținutul în liniște, în timp ce overflow: visible distruge aspectul.
Utilizatorii văd etichete tăiate ca 'Configura...' în loc de 'Configurații', sau butoane care se suprapun cu elemente vecine. Acțiunile critice devin ilizibile sau ne-clicabile.
Cum să o rezolvi
Proiectați și implementați layout-uri flexibile care se adaptează la lungimea conținutului pentru toate localizările.
Înlocuiește lățimile fixe cu min-width, max-width și layout-uri flexibile. Folosește CSS Grid sau Flexbox pentru a distribui spațiul în mod dinamic.
Setează containerul de text pentru întreruperea rândului: folosește overflow-wrap: break-word și evită white-space: nowrap pentru conținut tradus.
Testați interfața cu pseudo-localizare care mărește toate șirurile cu 40% pentru a simula cel mai rău caz — chiar înainte de a trimite șirurile traducătorilor.
Eroare #5: Formatarea datelor și numerelor
Datele și cifrele par să pară universale. Dar 01/02/2025 înseamnă 2 ianuarie în SUA și 1 februarie în Europa. Virgula și punctul își schimbă semnificația în numere: 1,000.50 (SUA) vs 1.000,50 (Europa). Facând asta greșit, duce la confuzie, erori de date și pierderea încrederii.
['Nu formatați datele sau numerele manual cu șabloane de șir — folosiți întotdeauna API-urile Intl', 'Salvați toate datele în ISO 8601 și monedele în cea mai mică unitate (cent) intern', 'Verificați cu Locales care folosesc separatoare zecimale diferite, ordini de date diferite și calendare diferite']
Nu formați niciodată manual datele sau numerele folosind șabloane de tip string — utilizați întotdeauna API-urile Intl.
Stocați toate datele în ISO 8601 și valutele în cea mai mică unitate (cenți) intern.
Testați cu locale care folosesc separatoare zecimale diferite, ordinea datelor și calendare diferite.
Un scenariu tipic
Dezvoltatorul formatează o dată ca MM/DD/YYYY și un preț ca $1.234,50 — corect pentru utilizatorii din SUA.
Un utilizator german vede data 03/04/2025 și o citește ca 3 aprilie în loc de 4 martie — întâlniri ratate sau rezervări incorecte.
Rezultat: Utilizatorul rezervă un zbor pentru data greșită și contestă formatul prețului. Tichetele de asistență cresc cu 15% pe piața germană.
De ce este o problemă
Formatarea datelor și a numerelor afectează orice afișare de date în aplicația ta: tabele, grafice, formulare, facturi, rapoarte. O soluție globală acoperă sute de instanțe.
șiruri de formatare hardcodate, cum ar fi toLocaleDateString('en-US') sau formatarea manuală cu template literals ignoră localizarea reală a utilizatorului. Chiar dacă localizarea este corectă, dar calendarul este greșit (gregorian vs hijri) provoacă probleme.
Utilizatorii citesc datele incorecte și introduc datele în format greșit. Un utilizator european care vede 03/04/2025 poate interpreta ca 3 aprilie în loc de 4 martie — întâlniri ratate sau rezervări incorecte.
Cum rezolvi asta
Folosește API-ul Intl încorporat sau o bibliotecă de formatare compatibilă cu locale pentru toate datele, orele, numerele și valutele.
Înlocuiește formatarea manuală cu Intl.DateTimeFormat(locale) pentru date și Intl.NumberFormat(locale, { style: 'currency', currency }) pentru prețuri.
Stocați datele intern în format ISO 8601 (YYYY-MM-DD) și formatează-le doar pentru afișare cu localizarea utilizatorului.
Testează cu cel puțin 5 locali diferite: en-US, de-DE, ja-JP, ar-SA și zh-CN, pentru a acoperi principalele variante de formatare.
Eroare #6: Uitarea limbilor RTL
Limbile de la dreapta la stânga (RTL), cum arabi, ebraică și persană, sunt utilizate de peste 500 de milioane de oameni. Cu toate acestea, majoritatea aplicațiilor sunt proiectate doar pentru layouturi de la stânga la dreapta (LTR). Suportul RTL nu înseamnă doar inversarea textului — întreaga interfață trebuie să fie oglindită.
['Folosiți de la început proprietăți CSS logice (inline-start/end, block-start/end)', 'Testați aplicația dvs. cu dir='rtl' pe elementul HTML în fiecare revizuire de sprint', 'Creați o listă de verificare RTL pentru navigație, pictograme, formulare și afișaje de progres']
Folosiți de la început numai proprietăți CSS logice (inline-start/end, block-start/end).
Testați aplicația cu dir='rtl' pe elementul HTML la fiecare revizuire de sprint.
Creați o listă de verificare RTL pentru navigare, pictograme, formulare și indicatori de progres.
Un scenariu tipic
Dezvoltatorul folosește margin-left: 16px și text-align: left în întreaga aplicație — practică implicită LTR.
Aplicația pornește în Arabia Saudită. Săgețile de întoarcere arată înainte, barele laterale apar pe partea greșită, iar datele numerice sunt aliniate incorect.
Rezultat: Utilizatorii arabi părăsesc aplicația după 30 de secunde. Echipa are nevoie de 4 săptămâni de refactorizare CSS de urgență pentru a rezolva problema.
De ce este această problemă
Suportul RTL afectează fiecare componentă a aplicației tale. Implementarea RTL-ului ulterior necesită, de obicei, rescrierea a 30-50% din toate regulile CSS și verificarea fiecărui pictogramă și a fiecărui layout.
Proprietățile CSS precum margin-left, padding-right, text-align: left și float: left codifică direcția. Icoane cu sensuri direcționale (săgeți, afișări de progres) indică în direcția greșită. Chiar valorile border-radius trebuie să fie oglindite.
Utilizatorii arabii văd navigarea în colțul greșit, bara de progres funcționează în sens invers, iar textul se ciocnește cu elementele interfeței. Aplicația pare străină și inutilizabilă.
Cum rezolvi asta
Folosește proprietăți CSS logice și testează cu layout RTL de la început.
Înlocuiește toate proprietățile CSS fizice cu omoloagele lor logice: margin-left → margin-inline-start, padding-right → padding-inline-end, text-align: left → text-align: start.
Seta atributul dir pe rădăcina HTML în funcție de localizarea activă. Folosește pseudo-clasa CSS :dir(rtl) pentru suprascrieri RTL specifice.
Verifică toate pictogramele în funcție de sensul direcțional. Înlocuiește pictogramele cu orientare direcțională prin versiuni oglindite sau folosește CSS transform: scaleX(-1) pentru contexte RTL.
Eroare #7: Imagini cu text
A introducere text într-o imagine — fie în bannerele hero, butoane, infografice sau capturi de ecran — este un coșmar de localizare. Fiecare imagine cu text trebuie să fie redesenată pentru fiecare limbă, ceea ce crește costurile de design și întârzie lansările.
['Cel mai bun rezultat: nu introduceți niciodată text tradus direct în imaginile raster (PNG, JPG)', 'Folosiți suprapuneri de text CSS pe imaginile de fundal pentru bannerele hero și CTA-uri', 'Automatizați generarea de capturi de ecran pentru listările din App Store și paginile de marketing']
Nu introduceți text tradus direct în imagini raster (PNG, JPG).
Folosiți suprapuneri de text CSS pe imaginile de fundal pentru bannerele principale și CTA-uri.
Automatizați generarea capturilor de ecran pentru listările din App Store și paginile de marketing.
Un scenariu tipic
Un designer creează un banner promoțional cu textul 'Start Your Free Trial' introdus direct în imagine.
Echipa de localizare traduce toate șirurile UI, dar bannerul afișează încă text în engleză pe pagina în limba germană.
Rezultatul: pagina de destinație germană are un banner enervant în engleză. Crearea de bannere localizate pentru 15 limbi durează 3 zile de muncă de design și întârzie lansarea.
De ce este această problemă
O site de marketing tipic are 5-10 imagini cu text. În 15 limbi, acestea sunt 75-150 de variante de imagini care trebuie create, întreținute și actualizate la fiecare modificare a designului.
Textul încorporat în imagini (PNG, JPG, SVG cu text încorporat) nu poate fi extras de uneltele de traducere. Fiecare versiune localizată necesită ca un designer să editeze manual fișierul sursă, să îl exporte și să îl încarce.
Utilizatorii văd imagini cu text în limba străină, sau, mai rău, o combinație de interfață tradusă cu imagini netraduse. Acest lucru pare inconsistent și subminează încrederea în marcă.
Cum să-l rezolvi
Separă textul de imaginile folosind suprapuneri CSS, SVG-uri cu elemente de text care pot fi traduse sau generare dinamică de imagini.
Folosește CSS pentru a așeza textul tradus deasupra imaginilor de fundal: poziționează stratul de text cu poziționare absolute deasupra containerului imaginii.
Pentru infografice sau diagrame, utilizați SVG-uri cu elemente <text> care fac referințe la cheile de traducere, în loc să încorporați șiruri brute.
Pentru capturi de ecran ale aplicațiilor în materialele de marketing, automatizează generarea de capturi de ecran cu instrumente precum Fastlane (Mobile) sau Playwright (Web), care realizează capturi în fiecare localitate.
Eroarea nr. 8: Traduceri lipsă netratate
Traducerile sunt în timpul dezvoltării în continuare incomplete. Noile funcționalități adaugă șiruri mai repede decât pot traducătorii să le traducă. Fără o logică de fallback adecvată, traducerile lipsă provoacă blocări ale aplicației, elemente UI goale sau chei de traducere brute afișate utilizatorilor.
['Configure întotdeauna cel puțin un limbaj de fallback în configurația dvs. i20n', 'Înregistrați cheile de traducere lipsă în sistemul dvs. de monitorizare pentru urmărire', 'Stabiliți un nivel minim de acoperire a traducerilor înainte de a lansa o locale']
Configurați întotdeauna o limbă de fallback în configurația dvs. i18n.
Înregistrați cheile de traducere lipsă în sistemul dvs. de monitorizare pentru urmărit.
Stabiliți un nivel minim de acoperire a traducerilor înainte ca o locale să devină activă.
Un scenariu tipic
Un dezvoltator adaugă o nouă zonă 'Caracteristici Premium' cu 15 noi chei de traducere. Versiunea în engleză este livrată imediat.
Traducerile în franceză nu sunt încă finalizate. Pagina franceză afișează chei brute: 'premium.feature1.title', 'premium.feature1.description'.
Rezultatul: utilizatorii francezi văd o pagină plină de nume de chei dezvoltator. Echipa de suport primește zeci de rapoarte de erori.
De ce este o problemă
Cu cât crește aplicația ta, cu atât crește decalajul dintre șirurile în engleză și traducerile în alte limbi. O aplicație cu 100 de limbi și 2.000 de șiruri poate avea, în orice moment, peste 10.000 de traduceri lipsă.
Fără o fallback logic, cheia de traducere lipsă returnează undefined, null sau șirul brut al cheii (de exemplu 'checkout.confirmButton'). Motoarele de template pot genera erori, făcând pagina să se blocheze sau să nu redea nimic.
Utilizatorii văd o interfață defectă: butoane goale, etichete lipsă sau șiruri criptice precum 'nav.settings.title' în loc de text real. Acest lucru este confuz și neprofesionist.
Cum să-l rezolvi
Configurați o lanț robust de fallback și monitorizați acoperirea traducerilor în toate localele.
Configurează un lanț de fallback de limbă în configurația ta i18n: cheile în franceză (fr) lipsă vor reveni automat la engleză (en).
Adaugă un tratator pentru chei lipsă care să înregistreze cheile netraduse în sistemul tău de monitorizare (de exemplu, Sentry, Datadog), fără a afecta experiența utilizatorului.
Creează un tablou de monitorizare a acoperirii traducerilor care să urmărească gradul de finalizare pentru fiecare locale și să blocheze lansările atunci când acoperirea scade sub un prag (de exemplu, 95%).
Eroarea nr. 9: Probleme de codificare a caracterelor
Problemele de codificare a caracterelor sunt ucigașii ascunși ai localizării. Totul pare corect în engleză și în limbile europene, dar odată ce adaugi chineză, japoneză, coreeană, arabă sau emoji, apar caractere mutilate (mojibake). Aceste erori sunt notoriu dificil de detectat.
['Folosiți codarea UTF-8 peste tot — fișierele sursă, baza de date, răspunsurile API și meta tag-urile HTML', 'Folosiți utf8mb4 în MySQL (nu doar utf8), pentru a susține întregul domeniu Unicode, inclusiv emoji', 'Testați cu conținut real în CJK, arabă și emoji, pentru a detecta problemele de codare devreme']
Folosiți codarea UTF-8 peste tot — fișierele sursă, baza de date, răspunsurile API și metatag-urile HTML.
Folositi utf8mb4 în MySQL (nu utf8) pentru a susține întreaga gamă Unicode, inclusiv emoji.
Testează cu conținut real în CJK, arabă și emoji pentru a depista din timp probleme de codare.
Un scenariu tipic
Dezvoltatorii configurează o bază de date MySQL cu collation latin1 (vechiul standard). Codul sursei al aplicației folosește UTF-8.
Utilizatorii japonezi se înregistrează cu numele lor reale. Baza de date stochează '田中太郎' ca biți corupți.
Rezultatul: profilul utilizatorului afișează text deteriorat. Cu atât mai rău: căutarea și ordonarea se rup pentru toate numele CJK, afectând mii de utilizatori.
De ce este o problemă
Problemele de codificare se răspândesc prin întregul stack. O collation de bază de date configurat incorect poate corupe milioane de înregistrări — corectarea necesită migrații de date costisitoare.
Codificarea este inconsistentă pe întregul stack — UTF-8 în fișierele sursă, Latin-1 în baza de date și Windows-1252 în răspunsurile API — transformă caractere multibyte în '????' sau '日本èª'.
Utilizatorii văd texte tăiate, semne de întrebare sau casete goale unde ar trebui să apară limba lor. În cel mai rău caz, introducerile din formulare sunt permanent corupte în baza de date.
Cum să rezolvi acest lucru
Impuneti o codare UTF-8 consistentă în toate straturile stack-ului aplicației.
Setați toate fișierele sursă la UTF-8 (configurați editorul dvs. și .editorconfig). Adăugați <meta charset='UTF-8'> în HTML și 'Content-Type: application/json; charset=utf-8' în răspunsurile API.
Configurați baza de date pentru utf8mb4 (nu doar utf8, care în MySQL este un subset de 3 octeți). Setați collation-ul conexiunii la utf8mb4_unicode_ci.
Alegeți fonturi care să acopere sistemele de scriere țintă: latină, chirilică, CJK, arabă, Devanagari. Folosiți stack-uri de fonturi ale sistemului sau Google Fonts cu subseturi de limbă pentru încărcare optimă.
Testează implementarea ta de i18n.
Test de extindere a lungimii
Măriți toate șirurile traduse cu 30-40% pentru a simula creșterea lungimii textului în limbile mai verbose, cum ar fi germana, finlandeză sau greacă. Aceasta acoperă containere cu lățime fixă, etichete tăiate și butoane care depășesc spațiul înainte de a începeți să traduceți. Multe instrumente de pseudo-localizare oferă acest lucru ca o funcționalitate încorporată.
"Trimite" → "Trimite_40%_mai_lung" (40% mai lung)
Pseudo-localizare
Pseudolocalizarea înlocuiește fiecare caracter cu un echivalent accentuat (de exemplu, 'a' → 'á') și înconjoară șirurile cu marcaje precum [!! și !!]. Astfel devine imediat evident care șiruri sunt codificate în aplicație și care provin din sistemul de traducere. Rulează pseudolocalizarea ca parte a pipeline-ului CI pentru a surprinde regresiile automat.
Orice text pe ecran care nu este încadrat între [!! !!] marcaje este codificat în mod fix și trebuie externalizat. Acest test surprinde 95% din șirurile ignorate în mai puțin de un minut.
"Trimite mesaj" → "[!! Ñáçḥŕíçḥṫ ṡéñðéñ !!]"
Test de layout RTL
Chiar dacă nu ai traduceri în arabă sau în ebraică, poți testa layout-ul RTL adăugând dir='rtl' la elementul rădăcină HTML. Acest lucru dezvăluie rapid erorile CSS direcționale: pictograme aliniate greșit, margini pe partea greșită, navigare defectuoasă și elemente flex sortate incorect. Fă din asta o verificare standard în fiecare sprint — durează 10 secunde să comutați și surprinde problemele care altfel ar necesita săptămâni pentru a fi reparate în producție.
Lista de verificare i18n
['Toate textele afișate utilizatorului trebuie să fie în fișiere de resurse', 'Nu utilizați concatenarea de șiruri pentru a forma propoziții', 'Reguli de pluralizare cu ICU MessageFormat sau echivalent implementate', 'Formatările de date, ora și numere folosesc API-uri sensibile la localizare', 'Layout RTL cu conținuturi în arabă sau ebraică testate', 'Interfețe UI flexibile care să suporte extinderea textului de până la 40%', 'Limba de fallback configurată și testată pentru chei lipsă', 'Codificarea UTF-8 este coerentă în toate fișierele și baze de date', 'Metadatele App Store și Play Store localizate pentru fiecare piață', 'Capturi de ecran și active de marketing actualizate pentru fiecare limbă']