Wanneer lokalisatie meer is dan alleen EN, DE, IT, ES, FR, etc.
TLDR
- De content in S'gaw Karen van een klant vertoonde vreemde gestippelde cirkels in Firefox. In plaats van dit voor één taal op te lossen, zijn we een konijnenhol ingegaan dat uiteindelijk de weergave voor 43 schriften heeft verbeterd.
- De CMS valt nu terug op de Noto-lettertypen van Google voor schriften die het besturingssysteem niet kan tekenen, en laadt deze alleen wanneer een pagina ze daadwerkelijk nodig heeft.
- Het blijkt dat bij lokalisatie ook locale-codes, fallbacks, tekstrichting en lettertypen van groot belang zijn.
- Onze oplossing geldt voor de CMS, niet voor jouw frontend. Verderop in het artikel staat een checklist om je te helpen bij het zoeken naar de juiste lettertypen.
Wat is S'gaw Karen?
უკეთესი ការបង្ហាញ ለ ရှားပါး ⵜⵉⴼⵉⵏⴰⵖ
Dat betekent letterlijk "betere weergave voor zeldzame schriften" in het Georgisch, Khmer, Amhaars, Birmees en Tifinagh.
Tot vorige week hing het ervan af in welke browser je de CMS opende of dat deze allemaal correct werden weergegeven. 🫠
We ontvingen onlangs een supportverzoek van een klant om "de weergave van S'gaw Karen-tekst in Firefox te repareren". Dit leidde tot wat uitzoekwerk.
Om het kort te maken: S'gaw Karen wordt voornamelijk gesproken in Myanmar en Thailand, en een van onze klanten beheert hun content in deze taal. In Chrome ging het goed. Firefox vertoonde echter kleine gestippelde cirkels rondom tekens waar die absoluut niet hoorden te staan.
We hebben het opgelost (daarover later meer). Maar het onderzoek dat we deden, wierp een nieuw licht op zaken rondom "lokalisatie" waar ik minder vaak aan denk dan aan het 'Heilig Roomse Rijk' van Unicode. En als je een meertalige site op een headless CMS draait, is een groot deel van wat we hebben gevonden ook relevant voor jouw frontend.
De helft van dit artikel gaat over wat we hebben gedaan, en de andere helft over wat relevant kan zijn voor jouw eigen implementatie.
Lokalisatie is een 'stack'
Wees eerlijk: wanneer je zegt dat een site "gelokaliseerd" is, bedoel je waarschijnlijk dat deze is vertaald in het Engels, Duits, Italiaans, Spaans en Frans. Dat zijn vijf talen die allemaal hetzelfde alfabet gebruiken – het Latijnse. Dat is eerlijk gezegd niet erg uitdagend.
Stel dat je het iets uitgebreider hebt aangepakt en ook ondersteuning voor Mandarijn hebt toegevoegd. Lokalisatie: � . Of is dat zo? ❓
Echte lokalisatie is in feite een stapel (stack) van beslissingen, waarbij vertaling slechts één laag is:
| Laag | De vraag die het beantwoordt | Wat DatoCMS biedt |
|---|---|---|
| Model | Welke content wordt vertaald? | Lokalisatie per veld, en vertalingen die optioneel kunnen zijn per model. |
| Locale | Welke taal, voor welke regio? | Taal- en regiocodes zoals en-GB en pt-BR (niet alleen taal, want Duits in Zwitserland is VOLLEDIG anders dan Duits in Oostenrijk). |
| Workflow | Wie vertaalt, wie publiceert, wie doet de QA, en wanneer gaat het live? | Locale-gebaseerde permissies, publicatie en planning per locale, de AI Translations-plugin, vertaaltools. |
| Delivery | Wat gebeurt er als een vertaling ontbreekt? | fallbackLocales, locales en allFieldLocales in de Content Delivery API. |
| Richting | Welke kant op loopt de tekst? | Van links naar rechts (de meeste), van rechts naar links (bijv. Arabisch), van boven naar beneden (bijv. Kanji). |
| Rendering | Kan het scherm dit daadwerkelijk tekenen? | Noto fallback-lettertypen voor 43 schriften in de CMS (d.w.z. kan de CMS renderen wat je typt, ongeacht of de klant dit op jouw website kan zien). |
Het grootste deel van de discussie vindt plaats aan de bovenkant van deze stack (welke velden, welke workflow, welk AI-model). De onderkant is waar tekst in minder algemene schriften kapotgaat, en dat is lastig te ontdekken tenzij je er absoluut zeker van bent dat je lettertypekeuzes dit op de frontend voor je klanten kunnen renderen.
Taal ≠ Schrift ≠ Locale
Dit is het deel dat me echt in het konijnenhol trok.
Kort samengevat:
- Een taal is WAT mensen spreken.
- Een schrift is HOE het wordt opgeschreven.
- Een locale is een taal EN waar deze wordt gebruikt.
En deze drie lopen niet altijd in een rechte lijn.
S'gaw Karen wordt bijvoorbeeld geschreven in het Myanmar-schrift, net als het Birmees, Mon en Shan. Het repareren van Karen betekende dus het repareren van Myanmar, wat vervolgens al die vier talen oploste. Een mooie bonus.
Het werkt ook andersom. Servisch wordt geschreven in zowel het Cyrillisch als het Latijnse schrift, en Punjabi gebruikt Gurmukhi in India maar Shahmukhi in Pakistan.
Zelfs de taalcodes worden vreemd. Karen heeft geen ISO-code van twee letters. kar dekt alle Karen-talen als groep, en S'gaw Karen op zichzelf is ksw.
Daarnaast doen deze schriften dingen op het scherm waar je als Latijnse lezer niet op bent voorbereid:
- Myanmar en Balinees stapelen medeklinkers op elkaar.
- In het Myanmar en Khmer worden sommige klinkertekens na een medeklinker getypt, maar worden ze vóór die medeklinker getekend.
- Myanmar, Khmer en Lao plaatsen geen spaties tussen woorden.
- Zes van de 43 nieuwe schriften die we nu ondersteunen, lopen van rechts naar links: Adlam, Hanifi Rohingya, Mandaic, N'Ko, Syriac en Thaana.
Hier zijn er een paar, waarbij elk schrift zijn eigen naam schrijft:
| Schrift | Voorbeeld | Leest/klinkt als | Gebruikt voor |
|---|---|---|---|
| Myanmar | မြန်မာ | Myanmar | Birmees, S'gaw Karen, Mon, Shan |
| Georgisch | ქართული | Kartuli (Georgisch) | Georgisch, Mingreels, Svan |
| Ethiopisch | ግዕዝ | Ge'ez | Amhaars, Tigrinya, Tigre, Ge'ez |
| Khmer | ខ្មែរ | Khmer | Khmer |
| Tibetaans | བོད་ | Böd (Tibet) | Tibetaans, Dzongkha, Ladakhi |
| Cherokee | ᏣᎳᎩ | Tsalagi (Cherokee) | Cherokee |
| Tifinagh | ⵜⵉⴼⵉⵏⴰⵖ | Tifinagh | Tashelhit, Centraal Atlas Tamazight |
Tofu en gestippelde cirkels
Wanneer een schrift niet correct rendert, gebeurt dit meestal op een van deze twee manieren:
- Tofu (▯): De browser heeft elk beschikbaar lettertype gecontroleerd, maar geen enkel type bevatte dat teken. De browser geeft het op en tekent een leeg vierkantje. Dit wordt "tofu" genoemd omdat het lijkt op een blokje tofu.
- Gestippelde cirkels (◌): Dit is subtieler. De browser vond wel een lettertype, maar de text shaping engine kon de stukjes niet aan elkaar lijmen. Schriften zoals Myanmar bouwen elke lettergreep op uit een basisletter plus tekens erboven, eronder of eromheen. Wanneer het lettertype deze niet kan combineren, wordt het overgebleven teken op een gestippelde cirkel getekend. Dit is in feite de browser die zegt: "dit teken is zijn letter kwijtgeraakt".
Dat is wat onze klant zag.
Maar waarom gebeurde dit in Firefox en niet in Chrome? Omdat wat je ziet afhangt van je browser, je OS en welke lettertypen toevallig zijn geïnstalleerd. Elke combinatie kan een ander fallback-lettertype gebruiken voor hetzelfde teken, en sommige ondersteunen Karen terwijl andere dat niet doen. Dit betekent dat je het niet één keer kunt reproduceren, fixen en vervolgens afsluiten. Er zijn te veel combinaties.
De categorie oplossen in plaats van de bug
De snelle oplossing zou zijn geweest om één nieuw lettertype voor Karen te laden, te controleren of het in Firefox werkte en klaar.
In plaats van één taal te patchen, zijn we een niveau hoger gegaan:
- Los het op per schrift, niet per taal: Noto levert al één lettertype per schrift, dus één regel dekt elke taal die in dat schrift wordt geschreven.
- Dek elk schrift dat in modern gebruik is: Unicode houdt een officiële lijst bij (de Recommended en Limited Use schriften in UAX #31), en dat werd onze scope.
- Sla de schriften over die besturingssystemen al afhandelen: Latijn, Cyrillisch, Grieks, Arabisch, CJK, Hangul, Devanagari, Thai en een paar andere renderen vrijwel overal prima.
Uiteindelijk renderen 43 schriften en tientallen talen nu correct, gedekt door een handvol CSS-regels die niet aangepast hoeven te worden telkens wanneer er iemand met een nieuwe taal komt.
Als je iets soortgelijks debugt, controleer dan of je "taalbug" eigenlijk een "schriftbug" is. Als dat zo is, is het oplossen van het hele schrift meestal ongeveer net zoveel werk.
Waarom Noto?
De vraag is: waarom Noto, behalve omdat Google het zegt?
Het antwoord zit letterlijk in de naam. Noto = "no tofu".
Google heeft dit lettertype specifiek gebouwd om het fallback-lettertype te zijn dat alles dekt. Daarnaast:
- Het is open source onder de SIL Open Font License, dus we kunnen het bundelen en zelf serveren.
- Het is één ontwerpfamilie over honderden schriften, waardoor meertalige teksten er niet uitzien als "alfabetsoep".
- Het wordt geleverd als één lettertype per schrift, wat precies is hoe we het wilden laden.
- Android gebruikt het al als fallback, en Apple levert Noto-lettertypen voor schriften waarvoor ze zelf geen fonts hebben.
Leuk feitje: we hebben ook gekeken naar GNU Unifont, dat een enorm bereik aan tekens heeft. Maar dat is een pixel-lettertype en kan de combinaties en stapelingen die Myanmar nodig heeft niet aan. Dat zou Karen hebben gebroken voordat we de andere schriften hadden bereikt.
Daarnaast zijn we Italiaans, en Noto is een stadje in Sicilië. Geweldige granita.
Hoe het werkt
Elk Noto-lettertype wordt geregistreerd met @font-face en een unicode-range die alleen dat specifieke schrift beslaat. De browser downloadt een lettertype alleen wanneer de pagina daadwerkelijk een teken in dat bereik bevat. De lettertypen staan in de font-stack van de CMS na ons interface-lettertype en vóór het generieke sans-serif, dus Latijnse tekst ziet er precies hetzelfde uit als voorheen.
Het geheel is ongeveer 1 KB aan CSS zodra het is geminificeerd en gegzipped.
Als jouw projecten in het Latijn, Cyrillisch, CJK of Arabisch zijn, wordt er niets extra's geladen. Als een van je editors een record opent in Tifinagh, downloadt hun browser één keer één lettertype. Dat is alles.
Onthoud echter dat dit allemaal binnen de CMS gebeurt: de editor, de recordformulieren, de previews. Je API-responses zijn niet veranderd en je website ook niet. Dat deel is jouw verantwoordelijkheid.
***
Lijst van alle nieuwe schriften die DatoCMS nu ondersteunt:
- Adlam (Fula, Pular, Fulfulde)
- Armeens
- Balinees
- Bamum
- Batak (Toba, Karo, Mandailing)
- Canadese syllaben (Cree, Inuktitut, Ojibwe)
- Chakma
- Cham
- Cherokee
- Ethiopisch (Amhaars, Tigrinya, Tigre, Ge'ez)
- Georgisch (Georgisch, Mingreels, Svan)
- Hanifi Rohingya (Rohingya)
- Javaans
- Kayah Li (Rood Karen)
- Khmer
- Lao
- Lepcha
- Limbu
- Lisu
- Mandaïsch
- Meetei Mayek (Manipuri)
- Miao (A-Hmao, andere Miao-talen)
- Myanmar (Birmees, S'gaw Karen, Mon, Shan)
- N'Ko (Bambara, Mandinka, Maninka)
- New Tai Lue (Tai Lü)
- Newa (Newar)
- Nyiakeng Puachue Hmong (Wit Hmong, Groen Hmong)
- Ol Chiki (Santali)
- Osage
- Saurashtra
- Sinhala (Sinhala, Pali)
- Sundanees
- Syloti Nagri (Sylheti)
- Syrisch (Klassiek Syrisch, Assyrisch, Turoyo)
- Tai Le (Tai Nüa)
- Tai Tham (Noord-Thai, Tai Khün, Tai Lü)
- Tai Viet (Tai Dam, Tai Dón)
- Thaana (Dhivehi)
- Tibetaans (Tibetaans, Dzongkha, Ladakhi)
- Tifinagh (Tashelhit, Centraal Atlas Tamazight)
- Vai
- Wancho
- Yi (Nuosu)
Groetjes,