本地化的Crystal Reports

5

如何在Crystal Reports中本地化标签(列标题、字段标签、页眉/页脚等)?

我们目前使用的是XI R2 SP4,但正在考虑迁移到2008。看起来2008提供了更好的查看器UI本地化功能。它是否有内容本地化支持?

5个回答

3
发现了一种在Crystal Reports中本地化DateTime等值的方法。
例如,如果日期为2009年8月,并且文化是法语,则会显示为août-2009。
所有这些都不需要将当前线程文化切换为法语。
相关代码段(示例):
            //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());

2
我能想到的两个选项是:1)为每个本地化版本单独创建报告(这很快变得混乱,我不建议这样做)或2)从应用程序(例如c# windows/web应用程序)生成报告,然后您可以使用.net的本地化标准并在代码中设置所有本地化文本(从资源文件中读取)来实现本地化。

我不确定2008年是否适用,但我们也在使用XI R2。我们有每种语言的本地化报告,但只因为我们*知道*我们只需要三个不同的本地化版本。

#2 是使用 RDC 扫描每个文本字段并替换为本地化文本吗? - Aidan Ryan
是的 - 我从未尝试过,所以我不确定会有什么麻烦。 - Jeremy Cron
你认为返回本地化字符串的UFL怎么样?从每个标签字段调用它会导致性能问题吗? - Aidan Ryan
看我的回答,我们成功地选择了方案#2。我们在构建时自动进行一次本地化,并分发每个hreport的本地化版本。 - Aidan Ryan

1
一个客户要求我为他们开发本地化策略。我一直想写一篇文章介绍这方面的内容。多亏了你,我现在完成了这篇文章。http://www.cogniza.com/blog/?p=55 编辑:
我能够使用一个嵌入式子报表(在报表标题部分),引用一个本地化值的数据库。我原本会把它加到我的发布中,但它相当复杂。
另一个选择是创建一个用户函数库(UFL)来处理这些任务。将数据存储在数据库或XML文件中。然而,很可能会失去ContentLocale功能。

在链接失效的情况下概括这个想法:创建一个自定义函数,通过检查Crystal XI ContentLocale变量返回本地化字符串。 - Aidan Ryan
2
我不喜欢将实际翻译放入自定义函数本身的想法。这会在外包翻译时带来麻烦。 - Aidan Ryan

1
我们终于开始实现报告本地化了。在我们的应用程序中,加载Crystal Reports已经是用户体验中最慢/性能最差的部分,因此我们希望避免任何性能影响。我们决定的另一个想法是,在发布版本后翻译不会改变。
我们开发了一个使用Crystal Reports API(2008 - 因此没有RDC)的应用程序,并分为两个阶段。
第一阶段是抓取所有文本并输出到英语.resx文件中。最困难的部分是在函数中识别可翻译的文本,并用指示“不要翻译”的标记替换嵌入字段。
在本地化版本的resx返回后,应用程序的第二阶段将每个报告以及每个resx一起处理,并保存出新的报告,其中英语被替换为翻译文本。这也使我们能够仅在日语报告中切换字体为MS Gothic,从而避免了需要许可“通用”字体的需求。在“通用”字体(例如Arial Unicode MS)中的日语字符往往看起来很糟糕。
Crystal API很复杂,需要小心处理函数和嵌入字段中检测可翻译字符串的边缘情况。注意内置字段(如 PageNofM)不包含在花括号中(更不用说你应该将其替换为“Page {field} of {field}”,以便可以翻译“page”和“of”)。一个提示:使用控制器来替换现有项目,以克隆/修改副本,不能直接就地修改项目的文本内容。如果您选择这条路线,祝您好运,但最终我们认为这是最佳选择。

-1

单个水晶报告用于多种语言

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();

resBundle是什么?为什么if / else块中的代码相同? - Aidan Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接