2009-05-20 27 views
5

¿Cuál es un buen método para localizar etiquetas (encabezados de columna, etiquetas de campo, encabezados/pies de página, etc.) en Crystal Reports?Crystal Reports localizados

Actualmente estamos en XI R2 SP4 pero estamos buscando migrar a 2008. Parece que 2008 ofrece una mejor localización de la interfaz de usuario del visor. ¿Tiene una historia de localización de contenido?

Respuesta

2

Las dos opciones que puedo pensar son: 1) Tener un informe separado para cada versión localizada (esto se pone feo rápido y no lo recomiendo mucho) o 2) Generar el informe desde una aplicación (diga aC# windows/aplicación web) y luego puede localizar utilizando los estándares de localización .net y establecer todo el texto localizado (leer desde los archivos de recursos) en el código.

No estoy seguro acerca de 2008 pero también estamos en XI R2. Tenemos informes localizados para cada idioma, pero solo porque * sabemos * que solo necesitaremos tres versiones localizadas diferentes.

+0

# 2 sería el uso de la RDC para escanear a través de cada campo de texto y reemplazar con texto localizado? –

+0

Sí, nunca lo he hecho, así que no estoy seguro de qué tipo de dolores de cabeza están involucrados. –

+0

¿Qué opinas sobre un UFL que devuelve cadenas localizadas? Llamar a eso de cada campo de etiqueta sería un problema de rendimiento? –

0

Un cliente me pidió que desarrollara una estrategia de localización para ellos. He querido escribir un artículo sobre eso. Gracias a ti, he hecho exactamente eso. http://www.cogniza.com/blog/?p=55

Editar:

yo era capaz de utilizar un subinforme incorporado (en la sección de informe-header) que hace referencia a una base de datos de los valores de localización. Hubiera agregado eso a mi publicación, pero fue bastante complejo.

Otra opción es crear una biblioteca de funciones de usuario (UFL) que maneje estas tareas. Almacene los datos en una base de datos o archivo XML. Sin embargo, es muy probable que pierda la funcionalidad ContentLocale.

+0

Resumiendo la idea en caso de rotura de enlace: cree una función personalizada que devuelva una cadena localizada marcando la variable Crystal XI ContentLocale. –

+2

No me gusta la idea de colocar las traducciones reales en la función personalizada. Esto creará dolores de cabeza al subcontratar traducciones. –

2

Encontré una forma de localizar valores como DateTimes en Crystal Reports.
Por ejemplo, si la fecha es agosto de 2009 y la cultura es francesa, entonces se mostraría como août-2009.
Todo esto SIN cambiar la cultura de subprocesos actual a francés.

fragmento de código en cuestión (ejemplo):

  //Locale must be set BEFORE report is opened 
      if (this.IsEnglish) 
      { 
       ReportDoc.ReportClientDocument.PreferredViewingLocaleID = 
        CrystalDecisions.ReportAppServer.DataDefModel.CeLocale.ceLocaleEnglishCanada; 
       ReportDoc.ReportClientDocument.LocaleID = 
        CrystalDecisions.ReportAppServer.DataDefModel.CeLocale.ceLocaleEnglishCanada; 
       ReportDoc.ReportClientDocument.ProductLocaleID = 
        CrystalDecisions.ReportAppServer.DataDefModel.CeLocale.ceLocaleEnglishCanada; 
      } 
      else 
      { 
       ReportDoc.ReportClientDocument.PreferredViewingLocaleID = 
        CrystalDecisions.ReportAppServer.DataDefModel.CeLocale.ceLocaleFrenchCanada; 
       ReportDoc.ReportClientDocument.LocaleID = 
        CrystalDecisions.ReportAppServer.DataDefModel.CeLocale.ceLocaleFrenchCanada; 
       ReportDoc.ReportClientDocument.ProductLocaleID = 
        CrystalDecisions.ReportAppServer.DataDefModel.CeLocale.ceLocaleFrenchCanada; 
      } 

      //Load the report from file path 
      ReportDoc.Load(reportPath.ToString()); 
1

finalmente llegamos en torno a la implementación de informe de localización. La carga de Crystal Reports ya es la parte más lenta/peor de la experiencia del usuario en nuestra aplicación, por lo que queríamos evitar cualquier impacto en el rendimiento. La otra idea que informó nuestra decisión fue que las traducciones no cambiarán dentro de un lanzamiento enviado.

Desarrollamos una aplicación que utiliza la API de Crystal Reports (2008, por lo que no hay RDC) y funciona en dos fases.

La primera fase es raspar todo el texto y la salida a un archivo inglés .resx. La parte más difícil de esto es identificar texto traducible dentro de funciones y reemplazar campos incrustados con tokens que indican "no traducir".

Después de que vuelven las versiones localizadas del resx, la segunda fase de la aplicación toma cada informe junto con cada resx y guarda nuevos informes con inglés reemplazado por texto traducido. Esto también nos permitió cambiar las fuentes solo en informes japoneses a MS Gothic, evitando así la necesidad de licenciar una fuente "universal". Los caracteres japoneses en fuentes "universales" (por ejemplo, Arial Unicode MS) tienden a parecer basura.

La Crystal API es bizantina, y debe tener cuidado con los casos de borde alrededor de la detección de cadenas traducibles dentro de funciones y campos incrustados.Tenga cuidado con los campos integrados como PageNofM, no están encerrados entre llaves (sin mencionar que debe reemplazar esto con la página {campo} de {campo} para que se pueda traducir "página" y "de"). Un puntero, use los controladores para reemplazar los elementos existentes con copias clonadas/modificadas, no puede simplemente modificar el contenido de texto de los elementos en su lugar. Buena suerte si sigues esta ruta, pero al final creemos que es la mejor opción.

-1

cristal único informe Uso de varios idiomas

if (CultureInfo.CurrentCulture.Name == "en-US") 
{ 
    (obj.ReportDefinition.ReportObjects["lbleverest"] as TextObject).Text = resBundle.GetString("Localization", "everest"); 
    (obj.ReportDefinition.ReportObjects["lblmandlicode"] as TextObject).Text = resBundle.GetString("Localization", "SocietyCode"); 
    (obj.ReportDefinition.ReportObjects["MandliName1"] as FieldObject).ApplyFont(new Font(resBundle.GetString("Localization", "Font"), Convert.ToInt32(resBundle.GetString("Localization", "FontSize")), FontStyle.Regular)); 
    (obj.ReportDefinition.ReportObjects["shortName1"] as FieldObject).ApplyFont(new Font(resBundle.GetString("Localization", "Font"), Convert.ToInt32(resBundle.GetString("Localization", "FontSize")), FontStyle.Regular));   
}  
else  
{  
    (obj.ReportDefinition.ReportObjects["lbleverest"] as TextObject).Text = resBundle.GetString("Localization", "everest");  
    (obj.ReportDefinition.ReportObjects["lblmandlicode"] as TextObject).Text = resBundle.GetString("Localization", "SocietyCode");  
    (obj.ReportDefinition.ReportObjects["MandliName1"] as FieldObject).ApplyFont(new Font(resBundle.GetString("Localization", "Font"), Convert.ToInt32(resBundle.GetString("Localization", "FontSize")), FontStyle.Regular));  
    (obj.ReportDefinition.ReportObjects["shortName1"] as FieldObject).ApplyFont(new Font(resBundle.GetString("Localization", "Font"), Convert.ToInt32(resBundle.GetString("Localization", "FontSize")), FontStyle.Regular));  
} 

obj.DataDefinition.FormulaFields["lang"].Text = "'" + CultureInfo.CurrentCulture.Name + "'";  
cv.crystalReportViewer1.ReportSource = obj;  
cv.Show(); 
+0

¿Qué es 'resBundle'? ¿Por qué el código en los bloques if/else es el mismo? –

Cuestiones relacionadas