Arabų kalbos versijos išdėstymas atrodo sugadintas, nors vertimas geras. Šoninė juosta lieka kairėje, grįžimo rodyklė rodo į kairę, avataras glaudžiasi prie kairiojo kiekvienos kortelės krašto: kiekvienas žodis arabiškas, tačiau kiekvienas langelis liko ten, kur jį paliko angliška versija. Teksto kryptis yra HTML atributas ir CSS sprendimų rinkinys, esantis jūsų komponentuose — joks katalogo failas jos neperduoda. globalize.now — DI pagrįsta lokalizacijos infrastruktūra, ištraukianti eilutes ir sinchronizuojanti katalogus po kiekvieno „Git“ „push“.
Kodėl mano Lovable programa arabų kalba vis dar skaitoma iš kairės į dešinę?
Nes kryptis yra dokumento ir stilių aprašo savybė, o ne pranešimo savybė.
Jūsų katalogai yra pradinių ir išverstų eilučių poros. Kai jie sukompiliuojami ar ir jūsų komponentai jį atvaizduoja, pasikeičia žodžiai, bet niekas daugiau. Nesvarbu, ar tai Lingui, į kurį rašo globalize.now, ar react-i18next. Nė vienas formatas neturi vietos nurodyti, kad „šoninė juosta turi būti kitoje pusėje“.
Turi pasikeisti du dalykai. dir atributas elemente html nurodo naršyklei, kuria kryptimi eina eilutės ašis. CSS turi nustoti įvardyti kraštines ir pradėti įvardyti šios ašies pradžią bei pabaigą. Visa kita išplaukia iš šių dviejų pakeitimų.
Kas iš tikrųjų sugenda pridėjus arabų kalbą prie Lovable programos?
Problemos atsiranda nuspėjamose vietose, ir visos jos susijusios su stiliais, o ne tekstu.
- Navigacijos stalčiai ir šoninės juostos lieka fizinėje kairėje pusėje.
- Ševronai, grįžimo rodyklės ir eigos indikatoriai rodo netinkama kryptimi.
- Asimetriškas vidinis tarpas pritvirtina turinį prie netinkamo krašto, todėl etiketės susigrūda vienoje pusėje.
text-leftantraštėje laiko arabų kalbą pririštą prie kairiosios konteinerio pusės.- Absoliučiai pozicionuojami ženkleliai ir uždarymo mygtukai atsiduria priešingame kampe, nei tikisi skaitytojas.
- Kairiniai rėmeliai, žymintys aktyvų sąrašo elementą, atsiranda galiniame, o ne pradiniame krašte.
- Angliškas produkto kodas arabiškame sakinyje be krypties nuorodos persirikiuoja nenuspėjamai.
Nė viena iš šių problemų nėra vertimo klaida. Kiekviena jų kyla dėl fizinės krypties, įrašytos klasės pavadinime.
Kaip nustatyti teksto kryptį pagal lokalės žymą?
Paklauskite lokalės, kokią kryptį ji naudoja, ir įrašykite atsakymą į dokumentą.
Intl.Locale.prototype.getTextInfo() grąžina ltr arba rtl kryptį pagal lokalės žymą. 2026 m. liepą ši funkcija pasiekė „Baseline“ naujai prieinama būseną, o tai reiškia, kad ji įdiegta dabartinėse visų pagrindinių naršyklių versijose, bet ne daugelyje naršyklių, kurias iš tikrųjų naudoja jūsų lankytojai. Toliau pateiktą atsarginį variantą laikykite veikiančiu keliu, o API — sprendimu, kuris ilgainiui jį pakeis.
// getTextInfo() is not yet in TypeScript's bundled Intl.Locale definitions.
declare global {
namespace Intl {
interface Locale {
getTextInfo?(): { direction: "ltr" | "rtl" };
}
}
}
// Stopgap for runtimes without getTextInfo(). This set is the one place where
// adding a new right-to-left language still costs you a code change.
const RTL_FALLBACK = new Set([
"ar", "he", "fa", "ur", "ps", "sd", "yi", "dv", "ckb", "ug", "nqo", "syr",
]);
export function directionFor(locale: string): "ltr" | "rtl" {
let tag: Intl.Locale | undefined;
try {
tag = new Intl.Locale(locale);
} catch {
// Malformed tag. Fall through to the string path below.
}
const direction = tag?.getTextInfo?.().direction;
if (direction === "ltr" || direction === "rtl") return direction;
const language = tag?.language ?? locale.split(/[-_]/)[0].toLowerCase();
return RTL_FALLBACK.has(language) ? "rtl" : "ltr";
}
Svarbios abi try vietos. new Intl.Locale() netinkamai žymai išmeta RangeError, o getTextInfo() senesnėse vykdymo aplinkose tiesiog neegzistuoja. Tvarkyti tik antrą atvejį — įprasta klaida: iš užklausos eilutės gauta lokalė, pavyzdžiui, ar_EG, nukreipia funkciją į jos pačios atkūrimo kelią ir iškart grąžina ją atgal kaip nepagautą klaidą.
Nustatykite abu atributus ten, kur jūsų programa jau žino aktyvią lokalę. Lovable šiuo metu sugeneruoja dvi struktūras: Vite vieno puslapio programą ir serverio pusėje atvaizduojamą „TanStack Start“ programą, todėl patikrinkite, ką iš tikrųjų sugeneravo jūsų projektas. „TanStack Start“ atveju tai yra šakninio dokumento komponentas. Vite atveju — vieta, kur prijungiate i18n teikėją.
<html lang={locale} dir={directionFor(locale)}>
Įdėkite dir į html, o ne į apgaubiantį div. Portalai, modaliniai langai ir pranešimai atvaizduojami už jūsų komponentų medžio ribų, todėl jiems taip pat reikia jį paveldėti.
Kurias „Tailwind“ klases turiu pakeisti, kad palaikyčiau rašymą iš dešinės į kairę?
Tas, kurios įvardija fizinę kraštinę. Jų loginiai atitikmenys seka eilutės ašį ir patys apsiverčia, kai pasikeičia dir.
| Fizinė pagalbinė klasė | Loginis pakaitalas | Ką nustato |
|---|---|---|
| ml-4 / mr-4 | ms-4 / me-4 | margin-inline-start / margin-inline-end |
| pl-6 / pr-6 | ps-6 / pe-6 | padding-inline-start / padding-inline-end |
| left-0 / right-0 | start-0 / end-0 | inset-inline-start / inset-inline-end |
| text-left / text-right | text-start / text-end | Teksto lygiavimas eilutės ašyje |
| border-l / border-r | border-s / border-e | priekinis / galinis kraštas |
| suapvalintas kairysis / suapvalintas dešinysis kampas | suapvalintas pradžios / suapvalintas pabaigos kampas | priekiniai / galiniai kampai |
| plūduriuoti kairėje / plūduriuoti dešinėje | plūduriuoti pradžioje / plūduriuoti pabaigoje | plūduriavimas eilutės ašyje |
| išvalyti kairę / išvalyti dešinę | išvalyti pradžią / išvalyti pabaigą | išvalyti eilutės ašyje |
| slinkimo kairioji paraštė 4 / slinkimo dešinioji paraštė 4 | slinkimo pradžios paraštė 4 / slinkimo pabaigos paraštė 4 | slinkimo fiksavimo paraštė |
Tailwind paraščių dokumentacijoje poveikis parodytas tiesiogiai: ms-8 ir me-8, pateikti konteineriuose dir="ltr" ir dir="rtl", atsiduria priešingose pusėse. Loginės savybės Tailwind atsirado v3.3 versijoje, todėl seniai kuriamame projekte jų gali nebūti.
Dviem paslaugoms reikia ne pervadinimo, o atidesnio įvertinimo. space-x-* ir divide-x-* prideda tarpą bei kraštines tarp gretimų elementų, todėl apverstoje eilutėje jos atsiduria netinkamoje kiekvieno elemento pusėje. Būtent tokiam atvejui Tailwind pateikia space-x-reverse ir divide-x-reverse. Vertikalioms paslaugoms, tokioms kaip mt-* ir pb-*, nieko nereikia, nes kryptis valdo tik eilutės ašį.
Ko loginės savybės negali išspręsti?
Visko, kas koduoja kryptį už dėžutės modelio ribų — būtent čia praverčia rtl: ir ltr: variantai.
<ChevronRight className="rtl:rotate-180" />
<div className="bg-[url(/hero.svg)] bg-left rtl:bg-right" />
<div className="shadow-[4px_0_8px_rgba(0,0,0,.15)] rtl:shadow-[-4px_0_8px_rgba(0,0,0,.15)]" />
Čia patenka transformacijos, fono padėtys, šešėlių poslinkiai, gradientų kampai, karuselės slinkimo skaičiavimai ir piktogramos, reiškiančios „pirmyn“. Sąrašas turėtų būti trumpas. Jei rtl: rašote kas antram elementui, pagrindiniai stiliai vis dar yra fiziniai ir juos reikėtų konvertuoti.
Naudotojų kuriamam turiniui reikia atskiro sprendimo, o šie du atvejai skiriasi. Jei visas blokas yra kalba, kurios nekontroliuojate, dir="auto" leidžia naršyklei nustatyti bazinę bloko kryptį pagal pirmąjį stiprų simbolį.
<p dir="auto">{review.body}</p>
Jei kitos rašto sistemos tekstas įterptas į jau kryptingą sakinį, pavyzdžiui, angliškas SKU arabiškame tekste, dir="auto" nieko nedaro, nes nustato pastraipos bazinę kryptį, o ne izoliuoja eilutės fragmentą. Tokį fragmentą apgaubkite atskirai.
<bdi>{product.sku}</bdi>
Kodėl vertimo valdiklis negali pats apversti jūsų išdėstymo?
Nes valdiklis veikia su pateikto puslapio teksto mazgais, o krypties problema slypi stiliuose, pagal kuriuos tas puslapis sukurtas.
Vykdymo metu veikianti paslauga gali dokumentui pridėti dir="rtl" ir išversti matomas eilutes, kai angliška versija jau pateikta. Tačiau ji negali atverti jūsų komponentų ir pakeisti ml-4 į ms-4, nes ml-4 jau sukompiliuota į margin-left stilių faile, kurio paslauga nevaldo. Rezultatas — arabiškas tekstas iš kairės į dešinę veikiančiame išdėstyme.
Yra ir antra kaina. Lovalingo — kai kuriose Lovable programėlėse naudojama vykdymo metu veikianti vertimo paslauga — paskelbė, kad 2026 m. rugpjūčio 31 d. 23:59 CEST nutrauks veiklą. Jos migracijos rekomendacijose klientams nurodoma pereiti prie projekte valdomo internacionalizavimo ir prieš pašalinant paslaugą iš naujo patikrinti lokalės maršrutus, kanoninius URL bei hreflang. Išdėstymo pakeitimai, atlikti tiekėjo produkte, iškeliauja kartu su tiekėju. Loginės paslaugos ir dir atributas jūsų saugykloje — ne. Tą patį argumentą apie eilučių sluoksnį pateikia mūsų Lovalingo palyginimas.
Kaip užtikrinti, kad kitas Lovable raginimas to neatšauktų?
Konvertuokite vieną kartą, o fizines paslaugas padarykite matomas peržiūroje.
- Įdiekite darbo eigą. Lovable darbo srityje pridėkite
lovable-i18nįgūdį ir paraginkite Lovable nustatyti i18n. Už redaktoriaus ribų diegimo komanda yranpx skills add globalize-now/globalize-skills, o--allįdiegia jį visiems agentams. - Nustatykite kryptį pagal lokalę naudodami
directionForaukščiau, elementehtml. - Visuose komponentuose pakeiskite fizines paslaugas loginėmis, pradėdami nuo to, kas apgaubia jūsų puslapius.
rtl:variantus pridėkite tik transformacijoms, fonams, šešėliams ir kryptinėms piktogramoms, o eilutės krypties užsienio rašto fragmentams naudokite<bdi>.- Į peržiūros procesą įtraukite grep patikrą, kad naujai sugeneruota fizinė paslauga būtų atmesta dar prieš suliejimą.
rg -n '\b(ml|mr|pl|pr|scroll-m[lr])-|\b(float|clear|text)-(left|right)\b|\bborder-[lr]\b|\brounded-[lr]-|\b(left|right)-[0-9]' src/
Būtent penktasis žingsnis užtikrina ilgalaikį rezultatą. Lovable per kiekvieną raginimą iš naujo generuoja komponentus, o modelis, paprašytas pridėti nustatymų skydelį, rinksis ml-4, nes fizinės paslaugos dominuoja React kode, pagal kurį šie modeliai buvo mokomi. Patikra, dėl kurios užklausa atmetama, kainuoja mažiau nei po trijų savaičių arabiškoje ekrano kopijoje aptikta problema.
Eilučių ciklo dalis veikia pati. globalize.now ištraukia naujas įkoduotas eilutes iš to, ką sugeneravo Lovable, įrašo jas į jūsų katalogus ir sinchronizuoja kiekvieno Git išsiuntimo metu, todėl arabiška versija išlieka aktuali, kol toliau teikiate raginimus. Tai tas pats mechanizmas, aprašytas Vite vadove ir TanStack Start vadove, todėl vertimai nebesugenda su kiekvienu išsiuntimu.
Už arabų kalbos pridėjimą plane papildomai mokėti nereikia. Starter planas kainuoja 20 € per mėnesį vienai darbo sričiai, į jį įtraukta 20 € vertimo kredito — maždaug 200 000 žodžių — o vėliau naudojimas tęsiamas ta pačia kaina už simbolį. Nėra mokesčių už vietas ar kalbas, taip pat įtrauktos rašomos iš dešinės į kairę kalbos. Daugiau apie nustatymą rasite Lovable integracijos puslapyje, inžinerinės informacijos — kūrėjams skirtame puslapyje, o trumpesnį kelią netechniniams kūrėjams — vibe coderių puslapyje.
Vienas išdėstymo pakeitimas — ir jis lieka sutvarkytas
Kryptį jūsų saugykla nustato vieną kartą. Eilutės keičiasi kiekvieną kartą, kai pateikiate raginimą, o ši dalis veikia pati.
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