Traducerea de software folosind GNU gettext

GNU gettext este unul dintre cele mai utilizate instrumente pentru internaționalizarea software-ului liber. Acesta oferă o modalitate simplă, dar flexibilă de a localiza software-ul. Are un suport excelent pentru plural, poate adăuga context suplimentar la șirul tradus și există o mulțime de instrumente construite în jurul său. Bineînțeles că are un suport excelent în Weblate (vezi GNU gettext file format description).

Notă

Dacă intenționați să îl utilizați în software proprietar, vă rugăm să consultați mai întâi licențele, deoarece s-ar putea să nu fie potrivit pentru dumneavoastră.

GNU gettext poate fi utilizat într-o varietate de limbaje (C, Python, PHP, Ruby, JavaScript și multe altele) și, de obicei, cadrele de interfață cu utilizatorul au deja un anumit suport pentru acesta. Utilizarea standard se face prin intermediul apelului de funcție gettext(), care este deseori numit _() pentru a face codul mai simplu și mai ușor de citit.

În plus, oferă apelul pgettext() pentru a oferi un context suplimentar traducătorilor și ngettext() care poate gestiona tipurile de plural definite pentru limba țintă.

Fiind un instrument răspândit pe scară largă, acesta dispune de mai multe învelișuri care îi simplifică utilizarea; în loc de invocarea manuală a gettext descrisă mai jos, poate doriți să încercați unul dintre acestea, de exemplu intltool.

Prezentare generală a fluxului de lucru

GNU gettext utilizează mai multe fișiere pentru a gestiona localizarea:

  • PACKAGE.pot conține șiruri de caractere extrase din codul sursă, de obicei folosind xgettext sau unele aplicații de nivel înalt, cum ar fi intltool.

  • LANGUAGE.po conține șiruri de caractere cu o traducere într-o singură limbă. Acesta trebuie să fie actualizat de către msgmerge odată ce PACKAGE.pot este actualizat. Puteți crea noi fișiere de limbă folosind msginit sau în Weblate.

  • LANGUAGE.mo conține o reprezentare binară a LANGUAGE.po și este utilizat la rularea aplicației. De obicei, nu este păstrat sub controlul versiunii, ci este generat în momentul compilării cu ajutorul msgfmt. În cazul în care doriți să îl aveți în controlul versiunii, îl puteți genera în Weblate utilizând add-onul Generarea de fișiere MO.

În general, fluxul de lucru GNU gettext arată în felul următor:

digraph translations { graph [fontname = "sans-serif", fontsize=10]; node [fontname = "sans-serif", fontsize=10, shape=note, margin=0.1, height=0]; edge [fontname = "monospace", fontsize=10]; "Source code" -> "PACKAGE.pot" [label=" xgettext "]; "PACKAGE.pot" -> "LANGUAGE.po" [label=" msgmerge "]; "LANGUAGE.po" -> "LANGUAGE.mo" [label=" msgfmt "]; }

Exemplu de program

Un program simplu în C folosind gettext ar putea arăta după cum urmează:

#include <libintl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int count = 1;
    setlocale(LC_ALL, "");
    bindtextdomain("hello", "/usr/share/locale");
    textdomain("hello");
    printf(
        ngettext(
            "Orangutan has %d banana.\n",
            "Orangutan has %d bananas.\n",
            count
        ),
        count
    );
    printf("%s\n", gettext("Thank you for using Weblate."));
    exit(0);
}

Extragerea șirurilor traductibile

Odată ce aveți un cod care utilizează apelurile gettext, puteți utiliza xgettext pentru a extrage mesajele din acesta și a le stoca într-un .pot:

$ xgettext main.c -o po/hello.pot

Notă

Există programe alternative pentru a extrage șiruri de caractere din cod, de exemplu pybabel.

Acest lucru creează un fișier șablon, pe care îl puteți folosi pentru a începe noi traduceri (folosind msginit) sau pentru a le actualiza pe cele existente după modificarea codului (pentru aceasta veți folosi msgmerge). Fișierul rezultat este pur și simplu un fișier text structurat:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-23 11:02+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"

#: main.c:14
#, c-format
msgid "Orangutan has %d banana.\n"
msgid_plural "Orangutan has %d bananas.\n"
msgstr[0] ""
msgstr[1] ""

#: main.c:20
msgid "Thank you for using Weblate."
msgstr ""

Fiecare linie msgid definește un șir de tradus, șirul special gol de la început este antetul fișierului care conține metadate despre traducere.

Începerea unei noi traduceri

Cu șablonul instalat, putem începe prima noastră traducere:

$ msginit -i po/hello.pot -l cs --no-translator -o po/cs.po
Created cs.po.

Tocmai a fost creat cs.po și are deja câteva informații completate. Cel mai important este că a primit definiția corectă a formelor de plural pentru limba aleasă și puteți vedea că numărul de pluraluri s-a schimbat în funcție de aceasta:

# Czech translations for PACKAGE package.
# Copyright (C) 2015 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Automatically generated, 2015.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-23 11:02+0200\n"
"PO-Revision-Date: 2015-10-23 11:02+0200\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"

#: main.c:14
#, c-format
msgid "Orangutan has %d banana.\n"
msgid_plural "Orangutan has %d bananas.\n"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""

#: main.c:20
msgid "Thank you for using Weblate."
msgstr ""

Acest fișier este compilat într-o formă binară optimizată, fișierul .mo utilizat de funcțiile GNU gettext la momentul execuției.

Actualizarea șirurilor de caractere

Odată ce adăugați mai multe șiruri de caractere sau modificați unele șiruri de caractere în programul dumneavoastră, executați din nou xgettext care regenerează fișierul șablon:

$ xgettext main.c -o po/hello.pot

Apoi puteți actualiza fișierele de traducere individuale pentru a se potrivi cu șabloanele nou create (acest lucru include reordonarea șirurilor pentru a se potrivi cu noul șablon):

$ msgmerge --previous --update po/cs.po po/hello.pot

Importul în Weblate

Pentru a importa o astfel de traducere în Weblate, tot ce trebuie să definiți sunt următoarele câmpuri atunci când creați componenta (a se vedea Configurația componentei pentru o descriere detaliată a câmpurilor):

Domeniul

Valoare

Depozitul de cod sursă

URL-ul depozitului VCS cu proiectul dumneavoastră

Masca de fișier

po/*.po

Șablon pentru traduceri noi

po/hello.pot

Formatul fișierului

Alegeți gettext PO file

Limba nouă

Alegeți Crearea unui nou fișier de limbă

Și asta e tot, sunteți gata să începeți să vă traduceți software-ul!

Vezi și

Puteți găsi un exemplu de gettext cu mai multe limbi în proiectul Weblate Hello de pe GitHub: <https://github.com/WeblateOrg/hello>.