Jūsų mygtukai, navigacija ir tuščios būsenos yra vokiečių kalba. Produktų pavadinimai, kategorijos ir aprašymai vis dar anglų kalba. Tai ne jūsų i18n sąrankos klaida — tai jos riba. globalize.now yra DI pagrįsta lokalizavimo infrastruktūra: ji išskiria kietai įrašytas eilutes iš jūsų kodų bazės, sugeneruoja raktus ir lokalės katalogus bei sinchronizuoja juos po kiekvieno Git push’o. Ji skaito kodą, o ne eilutes, tačiau turinys, dėl kurio naudotojai atėjo, yra būtent eilutėse.
Tai išspręsti reikia pasirinkti schemą, o ne įrankį. Štai sprendimas, kuris atlaiko realų naudojimą.
Kodėl mano Lovable programėlės sąsaja išversta, o duomenų bazės turinys vis dar anglų kalba?
Nes eilučių išskyriklis gali matyti tik tai, kas įrašyta jūsų šaltinio failuose.
Lokalizuojant Lovable programėlę, skeneris pereina per komponentus ir išrenka kiekvieną rastą literalą: "Add to cart", "No results", "Sign in". Jie tampa pranešimų ID kataloge, o katalogas išverčiamas ir įrašomas į saugyklą. Šis procesas yra deterministinis ir visiškai apima sąsają.
Jis negali apimti duomenų bazės eilutės. products.name = 'Trail Runner' niekada nebuvo .tsx faile. Ji atsirado per formą, seed scenarijų arba importą ir saugoma Postgres: Lovable Cloud integruotoje galinėje sistemoje, veikiančioje su Supabase, arba jūsų pačių prijungtame Supabase projekte. Joks kodo skeneris jos neperskaitys, o pakartotinis išskyrimo paleidimas to nepakeis.
Todėl gaunate išverstą apvalkalą aplink anglišką turinį. Navigacijoje parašyta Warenkorb, o jame esantis produktas vadinamas Trail Runner, lightweight trail shoe for wet conditions. Naudotojai tai pastebi iškart, ir rezultatas atrodo prasčiau nei neišversta programėlė, nes susidaro įspūdis, kad darbas paliktas pusiaukelėje.
Kas Lovable programėlėje laikoma duomenų bazės turiniu?
Viskas, ką naudotojas arba administratorius gali pakeisti neatlikdamas diegimo. Įprastoje Lovable programėlėje tai yra:
- Produktų, planų arba skelbimų pavadinimai ir aprašymai
- Kategorijų, žymų ir būsenų etiketės, atvaizduojamos iš paieškos lentelės
- Rinkodaros tekstai, saugomi
pagesarbasectionslentelėje - El. laiškų ir pranešimų šablonai
- Į enum panašios reikšmės, kurias rodote tiesiogiai, pavyzdžiui,
status = 'pending_review' - Naudotojų sukurtas turinys, kuris paprastai tyčia paliekamas originalo kalba
Paskutinis punktas svarbus. Pagal numatytuosius nustatymus neversti naudotojų sukurto turinio. Ispanų kalba parašyta apžvalga turėtų likti ispanų kalba. Lokalizuokite tą turinį, kurį sukuriate ir išleidžiate jūs.
Visa kita — aplink šį turinį esanti sąsaja — lieka jūsų kataloguose. Šie du rinkiniai niekada neturėtų persidengti. Jei etiketė yra ir paieškos lentelėje, ir kietai įrašyta eilutėje, pasirinkite jai vieną vietą ir pašalinkite kitą variantą, kitaip išleisite du skirtingus vokiškus žodžius tai pačiai sąvokai.
Kaip Supabase saugoti duomenų bazės turinio vertimus?
Naudokite atskirą vertimų lentelę, susietą su eilutės ID ir lokalės stulpeliu.
create table product_translations (
product_id uuid not null references products(id) on delete cascade,
locale text not null,
name text not null,
description text,
primary key (product_id, locale)
);
create index product_translations_locale_idx on product_translations (locale);
Dabar japonų kalbos pridėjimas reiškia įterpti naują eilutę, o ne atlikti migraciją. Eilučių lygio saugos politikos taikomos vienai lentelei, o ne vis didėjančiam stulpelių rinkiniui. Trūkstamas vertimas reiškia trūkstamą eilutę — ją lengva rasti užklausoje ir lengva apie ją gauti įspėjimą.
Alternatyva — kiekvienam verčiamam laukui naudoti JSONB stulpelį:
alter table products
add column name_i18n jsonb not null default '{}'::jsonb;
-- { "en": "Trail Runner", "de": "Trail Runner", "fr": "Coureur de sentier" }
Tai greičiau sukurti prototipui ir tinka nedideliam, dažniausiai nekintančiam turiniui. Tačiau prarandate kalbai taikomus apribojimus, tampa sunkiau audituoti dalinius vertimus, o indeksavimas brangsta, kai lokalizuotą reikšmę pradedate filtruoti arba pagal ją rikiuoti.
Trečiasis modelis — po stulpelį kiekvienai kalbai (name_en, name_de, name_fr) — yra tas, kurio reikėtų vengti. Kiekviena nauja kalba reiškia schemos migraciją kiekvienoje lentelėje, o Lovable projekte tai reiškia pakartotinai prašyti agento keisti gamybines lenteles. Jei norite išsamesnio šio modelio aprašymo, viešas pg_i18n Postgres plėtinys įgyvendina vertimų lentelės modelį kaip rodinius su integruotu atsarginiu variantu. Verta jį perskaityti prieš galutinai pasirenkant struktūrą.
Kurį modelį pasirinkti?
Vertimų lentelę, nebent turinys yra labai mažas ir nekintantis.
JSONB rinkitės tik tada, kai turite mažiau nei kelis verčiamus laukus, nereikia pagal juos filtruoti ar rikiuoti ir neplanuojate leisti jų redaguoti niekam, išskyrus save. Visais kitais atvejais — jei yra administravimo sąsaja, planuojate pridėti kalbų arba turite daugiau nei kelis šimtus eilučių — rinkitės lentelę.
Kaip atvaizdavimo metu užklausti tinkamą kalbą?
Naudokite aiškiai apibrėžtą atsarginį variantą duomenų bazėje, kad programėlei nereikėtų tuo rūpintis.
create or replace function products_for_locale(p_locale text)
returns table (id uuid, slug text, name text, description text)
language sql stable as $$
select
p.id,
p.slug,
coalesce(t.name, base.name) as name,
coalesce(t.description, base.description) as description
from products p
left join product_translations base
on base.product_id = p.id and base.locale = 'en'
left join product_translations t
on t.product_id = p.id and t.locale = p_locale;
$$;
Tuomet iškvietimo vietai tereikia perduoti lokalę:
const { data: products } = await supabase
.rpc('products_for_locale', { p_locale: locale });
Kad tai veiktų su realiais duomenimis, svarbios dvi taisyklės. Pirma, coalesce į šaltinio kalbą, o ne į tuščią eilutę: iš dalies išverstas katalogas turėtų rodyti anglų kalbą, o ne tuščias korteles. Antra, perduodamas locale turi sutapti su maršruto segmente naudojama reikšme ir su reikšme, pagal kurią indeksuojami jūsų sąsajos katalogai. Vienas lokalių sąrašas, trys vartotojai: maršrutizatorius, katalogai, duomenų bazė.
Būtent šioje vietoje dauguma Lovable projektų pradeda skirtis. Maršrutizatorius žino apie de, katalogai sukurti de-DE, o duomenų bazėje yra eilutės su žyma german. Pasirinkite tikslų BCP 47 žymų rinkinį, kurį naudoja jūsų lokalės maršrutai, ir pritaikykite prie jo visa kita. Jei šių maršrutų dar nesukonfigūravote, atskirų stekų instrukcijose tai paaiškinta abiem Lovable generuojamiems stekams: Vite SPA versijai ir numatytajai TanStack Start SSR versijai.
Kodėl tiesiog neleisti vykdymo metu veikiančiam valdikliui išversti duomenų bazės teksto?
Nes jis veikia su atvaizduojamu puslapiu, o ne su jūsų duomenimis, ir šis skirtumas išryškėja trijose vietose.
JavaScript vertimo valdiklis perskaito visą tekstą, patekusį į DOM, ir vėliau jį pakeičia. Jis iš tiesų aptinka duomenų bazės eilutes — tai vienintelis dalykas, kurį valdikliai atlieka, o katalogai ne, todėl iš pradžių jie atrodo kaip visavertis sprendimas.
Problemos yra struktūrinės. Išverstos eilutės egzistuoja tik naršyklės sesijoje, todėl puslapį indeksuojantys paieškos varikliai mato šaltinio kalbą; pats Weglot pagalbos centras nurodo, kad jo JavaScript integracija nesuteikia SEO naudos, nes vertimai atvaizduojami kliento pusėje. Pataisymai saugomi tiekėjo valdymo skyde, o ne jūsų duomenų bazėje, todėl tikroji lauko reikšmė padalijama tarp dviejų sistemų. Be to, pakeitimas įvyksta po atvaizdavimo, todėl taip sukurtos išverstos programėlės kiekvieną kartą naršant trumpam parodo anglų kalbą.
Nė viena iš šių priežasčių nereiškia, kad tokį būdą reikia visiškai atmesti vidiniam įrankiui. Tačiau tai yra priežastis nekurti viešo, indeksuojamo daugiakalbio produkto remiantis juo.
Kaip išlaikyti abiejų sluoksnių sinchronizaciją?
Naudojant vieną lokalių sąrašą ir vieną paleidimo mechanizmą.
Kodo sluoksnis yra automatinis. Pridėkite lovable-i18n skill’ą savo Lovable darbo srityje ir paprašykite Lovable sukonfigūruoti i18n arba įdiekite jį vietoje naudodami:
npx skills add globalize-now/globalize-skills
Nuo tada po kiekvieno push’o bus paleidžiamas išskyrimas ir atidaromas vertimo pull request’as — nereikės nei valdymo skydo veiksmų, nei rankiniu būdu peržiūrėti lokalės failų. Tai tas pats ciklas, aprašytas straipsnyje kodėl Lovable vertimai sugenda po kiekvieno push’o.
Duomenų sluoksnis priklauso jums, tačiau jam reikia vieno sąmoningai įdiegto kablio: kaskart pridėjus lokalę, tas pats sąrašas, pagal kurį generuojami maršrutai ir katalogai, turėtų inicijuoti trūkstamų įrašų papildymą vertimų lentelėje. Lovable projekte praktiškas sprendimas — vieną kartą paprašyti agento parašyti sėklos funkciją, kuri perskaito lokalių sąrašą ir įterpia trūkstamas eilutes, naudodama šaltinio kalbos reikšmes. Trūkstamos eilutės tada užpildomos, o ne išgalvojamos, o coalesce tuo metu užpildo spragą.
Kainodara čia taip pat netrukdo. „Starter“ planas kainuoja 20 € per mėnesį vienai darbo sričiai ir kas mėnesį suteikia 20 € vertimų kredito — maždaug 200 000 žodžių. Viršijus šį kiekį taikomas viešai skelbiamas mokestis už simbolį. Nėra nei mokesčio už naudotoją, nei mokesčio už kalbą, todėl pridėjus penktą kalbą mokate tik už jos simbolius ir nieko daugiau. Užsiregistravę gaunate 5 € vertimų kredito, kortelės nereikia. Daugiau apie tai, kaip tai dera su agento kuriamu steku, rasite vibe coders ir developers puslapiuose.
Kas sugenda, kai lokalizacijos paslaugų teikėjas nutraukia veiklą?
Viskas, kas buvo saugoma jų serveriuose, ir niekas iš to, kas buvo saugoma jūsų serveriuose.
Tai ne hipotetinis scenarijus šį mėnesį. Lovalingo — vykdymo metu veikiantis vertimų sluoksnis, kurį pasirinko daugelis Lovable kūrėjų, — užsidarys 2026 m. rugpjūčio 31 d. 23:59 CEST. Tai patvirtinta jų pačių paslaugos uždarymo puslapyje; nauji projektai ir prenumeratos jau sustabdyti, o aktyviems klientams rengiami išsaugojimo eksportai. Įdomiausia jų pačių rekomendacija: klientams siūloma kartu įdiegti projekte valdomą internacionalizaciją ir pašalinti paslaugą tik tada, kai pakaitinis sprendimas bus patikrintas veikiančioje produkcinėje aplinkoje.
Tai visas argumentas vienu sakiniu — jį pateikia paslaugų teikėjas, kurio pasitraukimas šį argumentą įrodo. Į Git įtrauktas katalogas ir product_translations lentelė yra jūsų nuosavybė; jų veikimo būsenos nereikia tikrinti pas paslaugų teikėją. Valdomas vykdymo metu veikiantis sluoksnis yra priklausomybė, kuri atvaizduoja jūsų produkto tekstą, o priklausomybės baigiasi.
Jei šiuo metu migruojate nuo valdiklio, pirmiausia sutvarkykite duomenų sluoksnį. UI eilutes iš kodo bus galima išgauti iš naujo per kelias minutes. Tačiau duomenų bazėje esantys vertimai, jei jie niekada neegzistavo už paslaugų teikėjo skydelio ribų, nebegrįš. Mūsų Lovalingo palyginime aprašyta, ką patikrinti prieš ką nors pašalinant.
Kodo sluoksnio neturėtumėte tvarkyti rankiniu būdu. globalize.now išgauna jūsų eilutes, sugeneruoja katalogus ir kiekvieno įkėlimo metu atidaro vertimų pull request, todėl galite vieną kartą suprojektuoti duomenų sluoksnį ir daugiau juo nebesirūpinti.
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