Difference between revisions of "Translations / i18n / localizations for programs/es"

From Free Pascal wiki
Jump to navigationJump to search
Line 37: Line 37:
 
==Traduciendo Formularios, Módulos de Datos y Marcos==
 
==Traduciendo Formularios, Módulos de Datos y Marcos==
  
    Cuando la opción i18n está activada para el proyecto/paquete el IDE crea automáticamente un archivo .lrt para cada formulario, cada vez que se guarda la unidad. Por tanto cuándo se habilita la opción por primera vez hay que abrir, modificar y guardar los formularios. Por ejemplo, si guardas un formulario ''unidad1 .pas'' el IDE crea el archivo ''unidad1.lrt''. Y al compilar el IDE reúne todas las cadenas de todos los archivos .lrt y .rst en un único archivo .po, con el nombre del proyecto o del paquete, en el directorio i18n.
+
   Cuando la opción i18n está activada para el proyecto/paquete el IDE crea automáticamente un archivo .lrt para cada formulario, cada vez que se guarda la unidad. Por tanto cuándo se habilita la opción por primera vez hay que abrir, modificar y guardar los formularios. Por ejemplo, si guardas un formulario ''unidad1 .pas'' el IDE crea el archivo ''unidad1.lrt''. Y al compilar el IDE reúne todas las cadenas de todos los archivos .lrt y .rst en un único archivo .po, con el nombre del proyecto o del paquete, en el directorio i18n.
 +
 
 +
   PAr los formularios que se traducen en tiempo de ejecución, hay que asignar un valor  que apunte al achivo de traducción a ''LRSTranslator'' (definido en ''LResources'') en la sección de inicio de una de las unidades del proyecto.
 +
<Delphi> ...
 +
uses
 +
  ...
 +
  LResources;
 +
...
 +
...
 +
initialization
 +
  LRSTranslator:=TPoTranslator.Create('/ruta/al/archivo/po'); </Delphi>
 +
 
 +
&nbsp;&nbsp;&nbsp;La clase que traduce utilizando archivos ''.po'', TPoTranslator, no está disponible en la LCL. Esta es una posible implementación (tomada en parte  de ''DefaultTranslator.pas'' de la LCL):
 +
 
 +
<Delphi> unit PoTranslator;
 +
 
 +
{$mode objfpc}{$H+}
 +
 
 +
interface
 +
 
 +
uses
 +
  Classes, SysUtils, LResources, typinfo, Translations;
 +
 
 +
type
 +
 +
  { TPoTranslator }
 +
 
 +
  TPoTranslator=class(TAbstractTranslator)
 +
  private
 +
    FPOFile:TPOFile;
 +
  public
 +
    constructor Create(POFileName:string);
 +
    destructor Destroy;override;
 +
    procedure TranslateStringProperty(Sender:TObject;
 +
    const Instance: TPersistent; PropInfo: PPropInfo; var Content:string);override;
 +
end;
 +
 
 +
implementation
 +
 
 +
{ TPoTranslator }
 +
 
 +
constructor TPoTranslator.Create(POFileName: string);
 +
begin
 +
  inherited Create;
 +
  FPOFile:=TPOFile.Create(POFileName);
 +
end;
 +
 
 +
destructor TPoTranslator.Destroy;
 +
begin
 +
  FPOFile.Free;
 +
  inherited Destroy;
 +
end;
 +
 
 +
procedure TPoTranslator.TranslateStringProperty(Sender: TObject;
 +
  const Instance: TPersistent; PropInfo: PPropInfo; var Content: string);
 +
var
 +
  s: String;
 +
begin
 +
  if not Assigned(FPOFile) then exit;
 +
  if not Assigned(PropInfo) then exit;
 +
{DO we really need this?}
 +
  if Instance is TComponent then
 +
    if csDesigning in (Instance as TComponent).ComponentState then exit;
 +
{End DO :)}
 +
  if (AnsiUpperCase(PropInfo^.PropType^.Name)<>'TTRANSLATESTRING') then exit;
 +
  s:=FPOFile.Translate(Content, Content);
 +
  if s<>'' then Content:=s;
 +
end;
 +
 
 +
end. </Delphi>
 +
 
 +
    +
 +
    +  Alternatively you can transform the .po file into .mo (using msgfmt) and simply use the DefaultTranslator unit
 +
    +
 +
    +  <Delphi>
 +
    +  ...
 +
    +  uses
 +
    +  ...
 +
    +  DefaultTranslator;
 +
    +  </Delphi>
 +
    +
 +
    +  which will automatically look in several standard places for a .mo file (the disadvantage is that you'll have to keep around both the .mo files for the DefaultTranslator unit and the .po files for TranslateUnitResourceStrings).
 +
    +  If you use DefaultTranslator, it will try to automatically detect the language based on the LANG environment variable (overridable using the --lang command line switch), then look in these places for the translation (LANG stands for the desired language):
 +
    +
 +
    +  * <Application Directory>/LANG/<Application Filename>.mo
 +
    +  * <Application Directory>/languages/LANG/<Application Filename>.mo
 +
    +  * <Application Directory>/locale/LANG/<Application Filename>.mo
 +
    +  * <Application Directory>/locale/LC_MESSAGES/LANG/<Application Filename>.mo
 +
    +
 +
    +  under unix-like systems it will also look in
 +
    +
 +
    +  * /usr/share/locale/LANG/LC_MESSAGES/<Application Filename>.mo
 +
    +
 +
    +  as well as using the short part of the language (e.g. if it is "es_ES" or "es_ES.UTF-8" and it doesn't exist it will also try "es")
  
 
==Seleccionando el idioma en el arranque el programa==
 
==Seleccionando el idioma en el arranque el programa==

Revision as of 20:40, 22 March 2009

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) 한국어 (ko) polski (pl) português (pt) русский (ru) 中文(中国大陆)‎ (zh_CN)

Descripción general

   Cómo hacer que los programas utilicen diferentes cadenas para varios idiomas cómo inglés, chino, alemán, castellano, etc. Básicamente funciona de la siguiente forma: Añade un recurso de cadena (resourcestring) para cada literal, compila para obtener los archivos .rst y/o .po (el IDE lo hace automáticamente), crea un archivo .po para cada idioma (existen herramientas gráficas para ello) y utiliza las funciones de la unidadtranslations de la LCL para cargar el archivo adecuado al iniciar el programa.

Recursos de Cadena (Resourcestrings)

   Por ejemplo <delphi> resourcestring

   Etiqueta1 = 'Algo de texto';
   HolaMundo1 = 'Hola Mundo';</delphi>

   Son como constantes de cadena normales, lo que significa que se pueden asignar a cualquier cadena. Por ejemplo <delphi> Label1.Caption := HolaMundo1;</delphi>

   Al compilar se creará un archivo .rst por cada unidad, con el mismo nombre que esta, conteniendo los resursos de cadena (nombre y contenido)

Archivos .po

   Hay muchas herramientas gráficas libres (kbabel y poedit, por ejemplo) para editar archivos .po, que son texto simple al igual que los archivos .rst, pero con algunas opciones más, como una cabecera que proporciona los campos autor, la codificación, el idioma y fecha. Toda instalación de fpc proporciona la herramienta rstconv (windows: rstconv.exe). Esta herramienta se utiliza para convertir archivos .rst en archivos .po. El IDE realizar esta operación automáticamente.

   Ejemplo de uso de rstconv:

 rstconv -i unidad1.rst -o unidad1.po

Traduciendo

   Por cada idioma el archivo .po debe ser copiado y traducido. La unidad translation utiliza los códigos de idiomas habituales (en=inglés, de=alemán, es=español, it=italiano, ...) para buscarlos. Por ejemplo la traducción al alemán de unidad1.po se llamará unidad1.de.po. Por tanto hay que copiar el archivo unidad1.po en un archivo de nombre unidad1.it.po y así para todos los idiomas que queramos soportar y los traductores editaran el archivo .po específico de cada idioma.

   Nota para brasileños y portugueses:: El IDE y la LCL de Lazarus únicamente tienen traducciones de portugués de Brasil y estos archivos se denominan con la extensión 'pb.po' y no 'pt.po'.

Opciones del IDE para la actualización automática de archivos .po

  • La unidad que contiene los recursos de cadena debe añadirse al paquete o proyecto.
  • Hay que proporcionar la ruta a .po si los archivos están en un directorio separado. Por ejemplo crear un directorio idiomas en el paquete/proyecto. Para proyectos ir a Proyecto > Opciones de proyecto, pestaña i18n. Para paquetes ir a Opciones > Integración en IDE.

Traduciendo Formularios, Módulos de Datos y Marcos

   Cuando la opción i18n está activada para el proyecto/paquete el IDE crea automáticamente un archivo .lrt para cada formulario, cada vez que se guarda la unidad. Por tanto cuándo se habilita la opción por primera vez hay que abrir, modificar y guardar los formularios. Por ejemplo, si guardas un formulario unidad1 .pas el IDE crea el archivo unidad1.lrt. Y al compilar el IDE reúne todas las cadenas de todos los archivos .lrt y .rst en un único archivo .po, con el nombre del proyecto o del paquete, en el directorio i18n.

   PAr los formularios que se traducen en tiempo de ejecución, hay que asignar un valor que apunte al achivo de traducción a LRSTranslator (definido en LResources) en la sección de inicio de una de las unidades del proyecto. <Delphi> ...

uses
  ...
  LResources;
...
...
initialization
  LRSTranslator:=TPoTranslator.Create('/ruta/al/archivo/po'); </Delphi>

   La clase que traduce utilizando archivos .po, TPoTranslator, no está disponible en la LCL. Esta es una posible implementación (tomada en parte de DefaultTranslator.pas de la LCL):

<Delphi> unit PoTranslator;

{$mode objfpc}{$H+}
interface
uses
  Classes, SysUtils, LResources, typinfo, Translations;
type

 { TPoTranslator }
 TPoTranslator=class(TAbstractTranslator)
 private
    FPOFile:TPOFile;
 public
   constructor Create(POFileName:string);
   destructor Destroy;override;
   procedure TranslateStringProperty(Sender:TObject; 
   const Instance: TPersistent; PropInfo: PPropInfo; var Content:string);override;
end;
implementation
{ TPoTranslator }
constructor TPoTranslator.Create(POFileName: string);
begin
  inherited Create;
  FPOFile:=TPOFile.Create(POFileName);
end;
destructor TPoTranslator.Destroy;
begin
  FPOFile.Free;
  inherited Destroy;
end;
procedure TPoTranslator.TranslateStringProperty(Sender: TObject;
 const Instance: TPersistent; PropInfo: PPropInfo; var Content: string);
var
  s: String;
begin
  if not Assigned(FPOFile) then exit;
  if not Assigned(PropInfo) then exit;
{DO we really need this?}
  if Instance is TComponent then
   if csDesigning in (Instance as TComponent).ComponentState then exit;
{End DO :)}
  if (AnsiUpperCase(PropInfo^.PropType^.Name)<>'TTRANSLATESTRING') then exit;
  s:=FPOFile.Translate(Content, Content);
  if s<> then Content:=s;
end;
end. </Delphi>
    +
    +  Alternatively you can transform the .po file into .mo (using msgfmt) and simply use the DefaultTranslator unit
    +
    +  <Delphi>
    +  ...
    +  uses
    +   ...
    +   DefaultTranslator;
    +  </Delphi>
    +
    +  which will automatically look in several standard places for a .mo file (the disadvantage is that you'll have to keep around both the .mo files for the DefaultTranslator unit and the .po files for TranslateUnitResourceStrings).
    +  If you use DefaultTranslator, it will try to automatically detect the language based on the LANG environment variable (overridable using the --lang command line switch), then look in these places for the translation (LANG stands for the desired language):
    +
    +  * <Application Directory>/LANG/<Application Filename>.mo
    +  * <Application Directory>/languages/LANG/<Application Filename>.mo
    +  * <Application Directory>/locale/LANG/<Application Filename>.mo
    +  * <Application Directory>/locale/LC_MESSAGES/LANG/<Application Filename>.mo
    +
    +  under unix-like systems it will also look in
    +
    +  * /usr/share/locale/LANG/LC_MESSAGES/<Application Filename>.mo
    +
    +  as well as using the short part of the language (e.g. if it is "es_ES" or "es_ES.UTF-8" and it doesn't exist it will also try "es")

Seleccionando el idioma en el arranque el programa

   Para cada fichero .po hay que hecer una llamada a la función TranslateUnitResourceStrings de la unidad de translations de la LCL. Por ejemplo:

<delphi> {lo pimero: añadir las unidades "gettext" y "translations" en la cláusula uses}

   procedure TForm1.FormCreate(Sender: TObject);
   var
     PODirectorio, Idioma, IdiomaDevuelto: String;
   begin
     PODirectorio := '/ruta/a/lazarus/lcl/languages/';
     GetLanguageIDs(Lang, IdiomaDevuelto); // en la unidad "gettext"
     TranslateUnitResourceStrings('LCLStrConsts', PODirectorio + 'lclstrconsts.%s.po', Idioma, IdiomaDevuelto);
     MessageDlg('Título', 'Texto', mtInformation, [mbOk, mbCancel, mbYes], 0);
   end;</delphi>

Trabajos previstos / ToDos

IDE Development: Translations, i18n, lrt, po files