Cum faci traduceri complexe? O abordare interesantă

Cum faci traduceri complexe? O abordare interesantă

Dau câteodată de vreo secvență de cod care mă surprinde prin ingeniozitate sau prin abordare. Ăsta este un exemplu.

Dacă a trebuit vreodată să faci vreo traducere complexă în cod, cel mai probabil te-ai lovit de niște limitări. Cu cât sunt mai multe traduceri, cu atât mai mare riscul de conflicte ciudate.

Discourse este o platformă care trebuie să existe în câteva localizări, printre care și română. Cum extragi textul de tradus dacă ai ceva de genul:

[There are «5 unread»] [and «25 new» topics remaining], or browse other topics in «Category»

(ce este între «» este link, ce este între [] este opțional)

Direct din limbajul de programare ai nevoie de câteva condiționale întortocheate:

txt = '';
if UNREAD or NEW:
  txt += There are

if UNREAD:
  txt += «5 unread»
  If NEW
    txt += and

if NEW
  txt += «25 new» topics remaining

......

Iar asta ar fi așa, basic și hardcoded. Dar dacă ținem cont că treaba asta trebuie să fie accesibilă traducătorilor (deci nu în codul sursă), de numerele din text și de faptul că numerele au reguli de exprimare în unele limbi (e.g. „un subiect” vs „5 subiecte” vs „25 de subiecte”) dar în altele nu, că unele secțiuni sunt afișate doar în anumite condiții… Oh boy.

În Pragmatic Programmers am citit că un programator bun are abilitatea de a putea scrie propriul DSL – un mini-limbaj care îți rezolvă o problemă foarte specifică. Iar oamenii de la Discourse au făcut… fix asta.

Expresia de mai sus este codată într-un fișier .yml așa:

There { UNREAD, plural, =0 {} one { is <a href='{basePath}/unread'># unread</a> } other { are <a href='{basePath}/unread'># unread</a> } } { NEW, plural, =0 {} one { {BOTH, select, true{and } false {is } other{}} <a href='{basePath}/new'># new</a> topic} other { {BOTH, select, true{and } false {are } other{}} <a href='{basePath}/new'># new</a> topics} } remaining, or {CATEGORY, select, true {browse other topics in {catLink}} false {{latestLink}} other {}}

La o primă vedere pare extrem de complicat, doar că… nu este:

{ 
  UNREAD, // trimis de backend
  plural, // dată, număr, plural, timp, sau select
  =0 { Text afișat când sunt zero UNREAD }
  =2 { Când sunt 2 UNREAD } // sau orice număr
  one { text afișat când este un singur UNREAD }
  few { sub 20 } // (în română, dar în alte limbi poate fi ignorat, poate fi ajustat)
  other { peste 20 } 
}

(Știi cum se spune că testele pot ține loc de documentație? Uite aici)

Toată povestea asta, chiar dacă nu este perfectă, este good enough, pentru că are destulă flexibilitate pentru a traduce ditamai platforma (bine, pe de altă parte, nu este nevoie decât în foarte puține locuri de treaba asta).

Există și o bibliotecă JS pentru asta care, din ce îmi dau seama, face cam același lucru.

Un Comentariu

Adaugă un comentariurăspuns pentru

Poți adăuga bucăți de cod folosind [code]codul tău aici[/code], [js][/js], [php][/php] etc.

Link-urile în context sunt binevenite. Comentariile fără nume/email valid sunt șterse.
PS: Comentariul NU este editabil.

Acest sit folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.

Site-ul blog.iamntz.com utilizează cookie-uri. Continuarea navigării presupune acceptarea lor. Mai multe informații.

windows apple dropbox facebook twitter