As you may already be aware, SSRS does not inherently support multiple languages. And what I am about to demonstrate does not apply to data, just labels and text that are pre-populated on a report.
What I do is use database driven report text. I populate a parameter with the label text and then use code to retrieve the label. Since a parameter is nothing more than a key/value list, this works quite well. By setting this up in the database, you can allow your business users to maintain your labels, and not have to make any code or report changes if you need to add a new language!
First, I create a master Label table. This will be the list of labels that I will have available to me. I have another table called Language. This table obviously holds my list of available languages. And I have a third table called LabelText. This table holds the actual text in the different languages that will be placed on the report.
Here is the script:
CREATE TABLE [dbo].[Label](
[LabelID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](900) NOT NULL)
CREATE TABLE [dbo].[Language](
[LanguageID] [int] IDENTITY(1,1) NOT NULL,
[Language] [varchar](100) NOT NULL,
[Active] [bit] NOT NULL)
CREATE TABLE [dbo].[LabelText](
[LanguageID] [int] NOT NULL,
[LabelID] [int] NOT NULL,
[LabelText] [nvarchar](max) NOT NULL)
I set the LabelText up as
NVARCHAR to support Unicode character sets.
Then I populate the Label table with all of the labels that I will need on the reports. Here is a short example:
71 % Total
120 Address 1
121 Address 2
122 Address 3
I also populate the Language table with the languages that will be available:
1 English 1
2 Spanish 0
The LabelText table really does all of the work. It contains the label text in the language of choice.
I am fortunate enough to have a very good background as a software developer, so I created a web page to populate these two tables and the LabelText table. I let the business unit populate this table since my grasp of other languages is not the best.
Once those are set up and populated, it's time to turn to the report design.
Create a dataset called
Languages. Use it to retrieve the rows in the Language table.
Where Active = 1
Since populating all of the labels in a new language may take some time, we only want to load languages that are set to Active. This gives the business unit time to load the text, without giving the user the ability to select that language on a report.
Create a parameter called
Language. Populate it with the values from the
Languages dataset. Pick a default if desired.
Now create a dataset called
Labels. This dataset is going to pull back the rows from the label text for the selected language:
From LabelText (NOLOCK)
Where LanguageID = @Language
from LabelText lt (NOLOCK)
Where LanguageID = 1
and Not Exists ( Select 1
From LabelText z (NOLOCK)
Where LanguageID = @LanguageID
and z.LabelID = lt.LabelID)
This SQL pulls back all of the labels for the language selected, and then, for any label missing in that language, unions the labels in language 1 (in my case, ID 1 is English). This way you always have a label returned.
Go back to the report parameter screen and create a new parameter called
Labels. This parameter should be internal, multi-value, and an integer.
For the available values, populate from the
Labels dataset, and do the same for the default values. This gives us a parameter filled with the label ID and text, with all of them selected by default. Since you can only "see" the selected parameter values inside a report, and not the populated values, this is an important step.
In the report properties window, under the Code tab, add code similar to this to loop through the selected values in the
Labels parameter, and return the text for the ID passed in. Since this parameter is loaded with the translated version, this is what will populate your labels.
Public Function GetLabel(Parm as Parameter, LabelID as Integer, _
Optional AddColon as Boolean=False) as String
Dim t as Integer
For t = 0 to Ubound(Parm.Value)
If (Parm.Value(t) = LabelID) Then
if AddColon = true then
Return Parm.Label(t) & ":"
AddColon parameter. I put this in because I have a lot of fields in my reports that are setup like a data entry form: Label: Value. Since I didn't want to type +":" in every textbox, I just added it to the routine. You can add as much custom code in here as you want. This will make your job easier in the long run.
The last step is to use your label table as a lookup (I usually load it into Excel and sort it alphabetically) and add this formula to every label textbox:
And if you wanted the colon:
And that's it! Now you have multi-language report labels! I also have this documented on my blog.
You can view my blog here.