Development/Tutorials/Localization/i18n (gl)

From KDE TechBase
Revision as of 20:29, 29 June 2011 by Neverendingo (talk | contribs) (Text replace - "<code cppqt>" to "<syntaxhighlight lang="cpp-qt">")


Development/Tutorials/Localization/i18n


Writing Applications With Localization In Mind
Tutorial Series   Localization
Previous   recoméndase Introduction to Unicode, mais non é imprescindíbel
What's Next   Avoiding Common Localization Pitfalls
Further Reading   n/a

Resumo

Chegar a un público amplo de usuarios e programadores require que se poida traducir o software e que este se adapte cando se execute de xeito que sexa lingüística e culturalmente relevante para quen se sente diante dun computador. Este é o territorio da localización e este titorial guía nos pasos precisos para que unha aplicación sexa localizábel.

Que son a "internacionalización" e a "localización"?

A internacionalización, ou i18n ("i" seguido de 18 letras e despois por un "n"), é o proceso de escribir unha aplicación para que se poda executar en calquera "locale" (as informacións que describen os formatos e mensaxes dunha determinada língua ou país). Isto significa ter en conta cousas tais como:

  • as mensaxes de texto que se lle mostran ao usuario
  • a entrada de datos por parte do usuario, ficheiros e outras fontes
  • o formato das datas, números, moedas, etc.

A localización, ou l10n ("l" seguido de 10 caracteres e despois por un "n"), é o proceso de tomar unha aplicación internacionalizada e adaptala a un "locale" determinado.

En termos xerais, os programadores internacionalizan as súas aplicacións e as equipas de tradución localízanas.

Por que é isto importante?

O desenvolvemento do KDE ten lugar fundamentalmente en inglés, dado que esta lingua permite chegar a máis persoas nas comunidades de programadores e de tradutores. Porén, o inglés non é a lingua principal da maioría das persoas do planeta. De feito, menos dun 8% da humanidade fala inglés e menos dun 5% o fala como lingua materna. Mesmo na Internet, só o 35% de quen están en liña emprega o inglés como lingua principal e conforme máis e máis persoas se conectan, este número vai decrecendo. Para alén disto, a maioría das linguas, incluídas nove de cada dez das máis faladas, empregan caracteres que non están no ASCII na súa escrita. É doado ver, polo tanto, o por que fornecer software localizado se tornou nunha necesidade.

Como proxecto internacional que abrangue o mundo enteiro, esta localización é un valor central da cultura do KDE. De feito, mesmo se moitos programadores do KDE escriben o seu software en inglés, empregan o escritorio no seu "locale" nativo.

Código traducíbel mediante i18n()

Para se asegurar de que unha aplicación está preparada para ser localizada hai que seguir unhas regras simples. Hai que traducir todas as cadeas que sexan visíbeis para o usuario antes de que se lle mostren na pantalla; exceptúanse as mensaxes de depuración, as teclas de configuración e outros tipos semellantes de datos textuais.

O KDE fornece a clase KLocale como parte de libkdecore para facilitar os detalles técnicos da localización. O KLocale facilita no posíbel que os programadores fagan que o seu código admita o i18n, mais hai outras cousas que hai que ter en conta para que as aplicacións sexan utilizábeis noutras linguas e países.

O acceso a un obxecto KLocale global fornécese mediante KGlobal::locale(). Este obxecto KLocale créao KInstance automaticamente e ocúpase de todas as opcións relacionadas co i18n do usuario. Elimínase automaticamente cando se sae da aplicacións.

As traducións son posíbeis grazas ao método QString i18n(const char*), definido en klocalizedstring.h, no que hai que envolver todas as cadeas que haxa que mostrar. O QString que devolve i18n() é a cadea traducida (de ser preciso). Isto fai que crear widgets traducíbeis sexa tan doado como neste exemplo:

<syntaxhighlight lang="cpp-qt">

  1. include <klocalizedstring.h>

[...] QPushButton* myButton = new QPushButton(i18n("Translate this!"));

QString acepta o Unicode de maneira nativa, o que permite que todas as traducións se representen correctamente. Polo tanto, toda a xestión de cadeas que faga unha aplicación debería empregar QString.

Tip
Se a cadea que hai que traducir contén caracteres que non estean en UTF8, empregue o método utf8() para obter un char*.


ki18n

O método i18n() require que se crease un KInstance (p.ex. KApplication). Fornécese outro método para as cadeas que se creasen con anterioridade a isto: ki18n(). isto permite marcar como tais cadeas que habería que traducir máis tarde. O ki18n() devolve un KLocalizedString, que pode ser finalizado nun QString (isto é, traducido de verdade) despois de terse creado o KInstance, empregando o seu método toString().

O k18n() emprégase tipicamente nas cadeas que se pasan a KAboutData porque se constrúe antes de KApplication e só se pode empregar i18(n) despois da construción de KApplication. Para alén destes casos especiais, é máis seguro empregar i18n() se non se ten certeza de que o código se vaia executar despois da construción de KApplication ou doutro KInstance.

Engadir contexto con i18nc()

Existe un método extendido, i18nc() que toma dous argumentos const char*. O primeiro argumento é unha descrición de contexto adicional da segunda cadea que se ha de traducir. A primeira cadea emprégase para atopar a tradución correspondente adecuada no momento da execución e preséntaselles aos tradutores para axudar a comprender o significado da cadea.

Empregue i18nc() cando o propósito do texto poida ser ambiguo en ausencia doutro contexto. Por exemplo, considere un menú de contexto nun xestor de ficheiros cunha entrada chamada "View" que abre un visor do ficheiro seleccionado. Neste contexto, "View" é un verbo. Porén, a mesma aplicación pode ter tamén un menú chamado "View" na barra de menú. Neste contexto, "View" é un substantivo. Na versión en inglés da aplicación todo parece correcto, mais na maioría das demais linguas unha das dúas cadeas "View" será incorrecta.

Para alén disto, ás veces os tradutores precisan de axuda adicional para comprender a que se refire exactamente o texto durante o proceso de tradución.

No exemplo anterior do xestor de ficheiros, poderíase, polo tanto, escribir:

<syntaxhighlight lang="cpp-qt">contextMenu->addAction(i18nc("verb, to view something", "View")); viewMenu->addAction(i18nc("noun, the view", "View"));

Agora as dúas cadeas son traducíbeis correctamente, tanto polos tradutores humanos como no momento de execución por KLocale.

Empregue esta forma de i18n cando a cadea que haxa que traducir sexa curta ou o sentido difícil de discernir cando non se coñece exactamente o contexto. Por exemplo:

Use this form of i18n whenever the string to translate is short or the meaning is hard to discern when the context is not exactly known. For example:

<syntaxhighlight lang="cpp-qt">QString up = i18nc("Go one directory up in the hierarchy", "Up"); QString relation = i18nc("A person's name and their familial relationship to you.", "%1 is your %2", name, relationship);

Note
Tamén existe un método ki18nc("context","text") para fornecer o contexto para as cadeas que se constrúen antes de KInstance. Devolve un KLocalizedString, polo que hai que empregar o método toString() despois para convertelo nun QString.


Tamén se poden engadir contextos cando se deseñan formularios en QT Designer. Cada etiqueta dun widget, incluídas as suxestións e os textos "que é isto", ten un atributo "comment", que ten o mesmo propósito como primeiro argumento da chamada i18nc().

Contexto normal das frases frecuentes

A continuación hai unha táboa que mostra algunhas palabras e frases frecuentes en inglés e o contexto que hai que empregar con elas para asegurarse de que se traducen correctamente noutras linguas.

Contextos nromais
Frase Contexto Chamada i18nc Exemplo
Busy Refering to a person i18nc("A person is busy", "Busy")
Busy Refering to a thing i18nc("A thing is busy", "Busy")
Color Color mode, as opposed to Grayscale i18nc("Not Grayscale", "Color")
Creator Refering to a person i18nc("A person who creates", "Creator")
Creator Refering to software i18nc("Software", "Creator")
Display Refering to hardware i18nc("Hardware display", "Display")
Editor Refering to a person i18nc("A person who edits", "Editor")
Editor Refering to software i18nc("Software", "Editor")
Line Refering to drawing i18nc("Draw a line", "Line")
Line Refering to text i18nc("Line of text", "Line")
Name Refering to a name of thing i18nc("A thing's name", "Name") In theme change dialog: i18nc("Theme name", "Name")
Name Refering to first name and last name of person i18nc("Person's first and last name", "Name") In KAddessbook contact edit dialog: i18nc("Person's first and last name", "Name")
New Create smth i18nc("Action", "New")
New Status i18nc("New mail message", "New")
No Answer to a question i18nc("Answer to a question", "No")
No Availability of a thing i18nc("Availability", "No")
(Re)load (Re)load a document, medium etc. i18nc("(Re)load a document", "(Re)load")
(Re)load (Re)start a program, daemon etc. i18nc("(Re)start a program", "(Re)load")
Title Refering to a person i18nc("A person's title", "Title")
Title Refering to a thing i18nc("A thing's title", "Title")
Trash Refering to the action of emptying i18nc("The trash is not empty. Empty it", "Empty")
Trash Refering to the state of being empty i18nc("The trash is empty. This is not an action, but a state", "Empty")
Volume Refering to sound i18nc("Sound volume", "Volume")
Volume Refering to a filesystem i18nc("Filesystem volume", "Volume")
Volume Refering to books i18nc("Book volume", "Volume")
Yes Answer to a question i18nc("Answer to a question", "Yes")
Yes Availability of a thing i18nc("Availability", "Yes")

Plurais

Os plurais son moi distintos en canda lingua. Moitas linguas teñen plurais diferentes para 2, 10, 20, 100, etc. Cando a cadea que se quere traducir se refire a máis dun elemento, hai que empregar a terceira forma de i18n,i18np(). Esta toma as formas de singular e de plural do inglés como primeiros dous argumentos, seguidos dos argumentos substitutos, como sempre, mais un deles ao menos un deles ha ser un valor enteiro. Por exemplo:

<syntaxhighlight lang="cpp-qt">msgStr = i18np("1 image in album %2", "%1 images in album %2", numImages, albumName);

i18np() expándese a tantos casos como requira a lingua do usuario. En inglés son só dúas formas, mentres que noutras linguas poden ser máis, dependendo do valor do primeiro argumento con valor enteiro.

Observe que hai que empregar esta forma mesmo se a cadea se refire sempre a máis de un elemento, dado que algunhas linguas empregan unha forma de singular mesmo cando se refiren a un plural (tipicamente para 21, 31, etc.). Este código:

<syntaxhighlight lang="cpp-qt">i18n("%1 files were deleted", numFilesDeleted);

é, polo tanto, incorrecto, e debería ser:

<syntaxhighlight lang="cpp-qt">i18np("1 file was deleted",

    "%1 files were deleted",
    numFilesDeleted);

Para fornecer tanto contexto como formas de plural, empregue i18ncp como neste exemplo:

<syntaxhighlight lang="cpp-qt">i18ncp("Personal file", "1 file", "%1 files", numFiles);

Formato de datas e números

Cando o programa lle mostre un número ao usuario, halle de prestar atención aos separadores de decimais e de milleiros e ao símbolo da moeda (de existir) que se empregue. Estes símbolos difiren de rexión en rexión. Nos países de fala inglesa emprégase un punto (.) para separar a parte decimal dun número, mentres que nalgunhas linguas europeas, entre elas o galego, emprégase a vírgula (,). A continuación hai un resumo pequeno de funcións que axudan a formatar os números correctamente, tendo conta das convencións locais en beneficio do programador.

Funcións para formatar números
Formats a.. From a.. Function Prototype
Number String
QString formatNumber( const QString & numStr )
Number Integer, double
formatNumber( double num, 
              int precision = -1 )
Money String
formatMoney( const QString & numStr )
Money Number
formatMoney( double num, 
             const QString & currency,
             int digits = -1 )
Date String
formatDate( const QDate & pDate,
            bool shortFormat=false )
Time QTime
formatTime( const QTime & pTime, 
            bool includeSecs=false)
Date and time QDateTime
formatDateTime( const QDateTime &pDateTime,
                bool shortFormat = true,
                bool includeSecs = false )

Existen funcións semellantes para ler información fornecida polo usuario durante a execución no seu formato localizado, p.ex. readNumber() ou readMoney().

Calendarios

A programación de aplicacións que traballen con datas e horas, como os calendarios, é unha área moi complexa. Non é só que unha cadea que conteña unha data ou hora teña unha aparencia distinta baseada no "locale", senón que hai que ter en conta outros aspectos, tais como:

  • o día no que comeza a semana (vexa int weekStartDay())
  • cantos meses ten o ano
  • calendarios baseados na "era"
  • se se utiliza o formato de 24 horas (vexa bool use12Clock())

O Klocale fornece, entre outros, estes métodos:

Funcións de datos de calendarios
Formats a.. From a.. Function Prototype
Date QDate
formatDate( const QDate & pDate,
            bool shortFormat=false )
Time QTime
formatTime( const QTime & pTime,
            bool includeSecs=false )
Date and time QDateTime
formatDateTime( const QDateTime &pDateTime,
                bool shortFormat=true,
                bool includeSecs=false )
Warning
This section needs improvements: Please help us to

cleanup confusing sections and fix sections which contain a todo


fornecer máis información acerca dos distintos sistemas de calendario

Evitar problemas frecuentes

Existen un monte de problemas frecuentes que poden dificultar que se localice axeitadamente unha aplicación. Vexa Avoiding Common Localization Pitfalls para saber máis sobre eles e sobre como evitalos.

Note
Grazas a Lukáš Tinkl, a Matthias Kiefer e a Gary Cramblitt por escribir a versión orixinal deste titorial.