SSRS中的多语言支持

9
有没有办法显示/导出英文的SSRS报告到其他语言呢?
7个回答

6
很遗憾,没有简单的方法可以做到这一点:-( 我一直在尝试自己实现这个功能,但最终我所做的就是从调用应用程序(在我的情况下是一个ASP.NET应用程序)传递我想要在报表上显示的所有标签。
另一种方法可能是将文本片段存储在SQL Server表中,并向报表添加数据源以检索那些文本标签,然后将它们绑定到相应的控件。我尝试过类似的方法,但自己无法使其正常工作。
ASP.NET非常强大的本地化资源使其国际化,但尝试使SSRS具备多语言意识仍然是一件棘手的事情:-(

5
我通过一个有趣的技巧,使用.NET资源文件实现了多语言支持。每个报表控件都有一个未使用的属性叫做ValueLocId。使用这个属性,您可以为每个控件指定要使用的资源名称。这里的想法是,您将循环遍历报表定义,查找已设置ValueLocID属性的控件。如果已设置该属性,则用ValueLocID中指定的资源文本替换该控件的Text。因此,基本上的想法是:

  1. 将RDLC文件作为XML文件加载到内存中
  2. 使用XPath遍历XML文件,寻找ValueLocID属性
  3. 用ValueLocID中指定的资源替换该XML节点的innerText
  4. 使用RDLC文件的内存副本加载ReportViewer控件。

请参见下面的函数,它将完全执行我上面提到的操作。

Private Sub LocalizeReport()

    Dim xmlDoc As XmlDocument = New XmlDocument
    Dim asm As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
    'create in memory, a XML file from a embedded resource
    Dim xmlStream As Stream = asm.GetManifestResourceStream(ReportViewer1.LocalReport.ReportEmbeddedResource)

    Try
        'Load the RDLC file into a XML doc
        xmlDoc.Load(xmlStream)
    Catch e As Exception
        'HANDLE YOUR ERROR HERE
    End Try

    'Create an XmlNamespaceManager to resolve the default namespace
    Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(xmlDoc.NameTable)
    nsmgr.AddNamespace("nm", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition")
    nsmgr.AddNamespace("rd", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner")

    'IMPORTANT LINE BELOW
    'YOU WILL NEED TO SET THIS TO YOUR RESOURCE MANAGER, OTHERWISE NOTHING WILL WORK
    Dim rm As ResourceManager = New ResourceManager("Insurance.Subs.WinUI.Controls.Resources", asm)

    'Loop through each node in the XML file, that has the ValueLOCId property set.
    'Using this property as a workaround for localization support.  The value specified in this
    'property will determine what resource to use for translation.
    Dim node As XmlNode
    For Each node In xmlDoc.DocumentElement.SelectNodes(String.Format("//nm:{0}[@rd:LocID]", "Value"), nsmgr)  'XPath to LocID
        Dim nodeValue As String = node.InnerText
        If (String.IsNullOrEmpty(nodeValue) Or Not nodeValue.StartsWith("=")) Then
            Try
                Dim localizedValue As String = node.Attributes("rd:LocID").Value

                'Get the resource via string
                localizedValue = rm.GetString(localizedValue)
                If Not String.IsNullOrEmpty(localizedValue) Then
                    'Set the text value - via the retrieved information from resource file
                    node.InnerText = localizedValue
                End If

            Catch ex As Exception
                'handle error
            End Try
        End If
    Next

    ReportViewer1.LocalReport.ReportPath = String.Empty
    ReportViewer1.LocalReport.ReportEmbeddedResource = Nothing
    'Load the updated RDLC document into LocalReport object.
    Dim rdlcOutputStream As StringReader = New StringReader(xmlDoc.DocumentElement.OuterXml)
    Using rdlcOutputStream
        ReportViewer1.LocalReport.LoadReportDefinition(rdlcOutputStream)
    End Using

End Sub

1
但是对于基于服务器的 .RDL 文件无效(而这正是我正在处理的)。 - marc_s
是的,没错。这个解决方案只适用于本地托管的报告。 - jgallant

3

我真的不确定是否想要为报告中的每个标签调用自动化的谷歌服务..... - marc_s
@marc_s 不一定非得用那个,那只是一个例子。如果你使用nvarchar和一个存储过程,你也可以检索任何语言的标题的列信息。 - JonH

3

1
通过使用SQL dsTranslations数据集的方式(我不喜欢在XML中搞来搞去), 可以让您制作一个简单的界面,让您的客户填写翻译内容, 例如,快速的Lightswitch GUI。

enter image description here

使用这个数据集,我进行简单的查找来进行翻译。

=Lookup("WORDTOBETRANSLATED", Fields!Key.Value, Fields!Value.Value, "dsTranslation")

这是我个人使用的第二种方法,如果键不在dbTranslations中,则显示他们必须添加到db中的键。我可能可以更优雅地完成这个第二部分,非常欢迎反馈。
=Microsoft.VisualBasic.Interaction.iif(Lookup("WORDTOBETRANSLATED", Fields!Key.Value, Fields!Value.Value, "dsTranslation") = "", "WORDTOBETRANSLATED", Lookup("WORDTOBETRANSLATED", Fields!Key.Value, Fields!Value.Value, "dsTranslation"))

谢谢。这是一个非常好的无DLL解决方案。此外,由于某些限制,可以不将翻译存储在数据库中,而是在数据集中使用表值构造函数,如下所示:SELECT * FROM (VALUES ('en-US', 'label_1', N'一些文本。使用Replace函数替换一些标记,如{0}'), ('en-US', 'label_2', N'等等...'), ) AS Translation([Language], [Label], [Text]) WHERE [Language] = @Language - Janis Veinbergs
当我尝试将Lookup调用移入Code.MyTranslation函数时,我遇到了一个问题。它显示错误BC30451 Lookup未定义 :( 我错过了什么?这里需要添加命名空间前缀吗? - ullfindsmit

0
制作多语言的SSRS报表的简单方法是硬编码或使用sharedataset,但是如果使用共享数据集,我们将面临渲染性能问题。
下面是一种有效的方法,在报表中翻译标签并获得更好的性能(尤其是渲染性能):
步骤1:实现一个库来支持获取报表字典。以下示例仅供参考,应根据需要修改以返回正确的字典。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Data.SqlClient;

namespace CmsReportLibrary
{
    public class DictionaryLabel
    {
        DictionaryLabel()
        {
            
        }
        
        public static string[] GetDictionary(int languageid)
        {
            System.Data.SqlClient.SqlClientPermission oPerm = new System.Data.SqlClient.SqlClientPermission(PermissionState.Unrestricted);
            oPerm.Assert();
            SqlConnection oConn = new SqlConnection();
            oConn.ConnectionString = ConfigurationManager.ConnectionStrings["appconnectionstring"].ConnectionString;

            //oConn.ConnectionString = "Data Source=(local);Initial Catalog=Northwind;User Id=<>;Password=<>";

            //oConn.Open();
            //SqlCommand oCmd = new SqlCommand();
            //oCmd.Connection = oConn;
            //oCmd.CommandText = "..................";
            // ....................

            //oConn.Close(); 
            return new string[] {...............}; 
   //ex return new string[] { "Client||Klient", "Week||Woche", "Year||Jahr"};    

        }
    }
}

步骤2:编译库并将其复制到报告服务的Bin文件夹中

例如:将库复制到C:\Program Files\Microsoft SQL Server\MSRS10_50.R2\Reporting Services\ReportServer\bin

步骤3:修改ReportServer文件夹中的rssrvpolicy.config文件(例如:C:\Program Files\Microsoft SQL Server\MSRS10_50.R2\Reporting Services\rssrvpolicy.config),找到"$CodeGen$",并添加以下代码以让SSRS知道新库的位置。

<CodeGroup
        class="UnionCodeGroup"
        version="1"
        PermissionSetName="FullTrust"
        Name="CoDeMagSample"
        Description="CoDe Magazine Sample. ">
       <IMembershipCondition
            class="UrlMembershipCondition"
            version="1"
            Url="C:\Program Files\Microsoft SQL Server\MSRS10_50.R2\Reporting Services\ReportServer\bin\CmsReportLibrary.dll"
    />
</CodeGroup>

步骤4:在报告服务配置管理器中停止和启动报告服务

步骤5:将库应用到SSRS报告中 创建新报告或修改现有报告,该报告应具有languageid参数 通过以下方式为此报告设置库的引用: 右键单击报告,选择“报告属性” 单击“引用”选项卡 将库的引用粘贴到“添加或删除程序集”区域:

CmsReportLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

enter image description here

第六步:添加自定义代码以支持标签翻译
public Shared Dim ListLabel as String()

函数 GetListLabel(languageid as Integer) ListLabel = CmsReportLibrary.DictionaryLabel.GetDictionary(Parameters!LanguageId.Value) end function 函数 Translate(input as String) as String

dim i as Integer


For i=0 to UBound(ListLabel,1)
    if Instr(ListLabel(i), input) > 0 then
        Translate = Replace(ListLabel(i), input + "||","")      
        exit function
    end if

Next

'Not found, return any string you want
Translate = "not found"
end function

步骤7:添加新的报告变量 输入图像描述

列表标签变量的表达式

=Code.GetListLabel(Parameters!LanguageId.Value)

步骤8:翻译报告中的标签

修改标签表达式,使用自定义代码中的Translate方法进行翻译

例如:

=Code.Translate("Client")

=Code.Translate("Week")

0

我同意Igoy的观点,最近我按照codeproject中列出的步骤进行了操作,但是我想补充一下,当添加新的CodeGroup时,需要遵循的步骤有些不足,如果你将新的CodeGroup放在未命名的UnioncodeGroup之后(它的Url="$CodeGen$/*"),那么你尝试访问自定义程序集的尝试将会失败。

经过大量的挖掘,我在其中一个msdn页面上找到了确认信息(请参见“扩展的CodeGroup元素的放置”部分)。他们的措辞是“建议”,但从我的测试来看,至少在直接在报告服务器上进行测试时,这是必需的: http://msdn.microsoft.com/en-us/library/ms152828.aspx

在.config文件中,此位置的xpath如下(在wix中很有用): //PolicyLevel/CodeGroup/CodeGroup[[]@class='FirstMatchCodeGroup'[]]/CodeGroup[[]@PermissionSetName='ReportLocalization'[]]


我不明白为什么我的回答被认为是“没有用的”。在参考了社区中几个本地化SSRS的示例后,我花了额外的三天时间才找到了我在这里分享的有用信息。能否请那些投反对票的人解释一下原因呢?你们的解释可能会帮助我成为更好的SO贡献者 :) - idclaar

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