Как локализовать отчет в FastReport .NET

Одна из нетривиальных задач, которая может быть поставлена разработчику – локализация отчетов. То есть создание мультиязычных отчетов. Что это значит?

Для разных языков будет применяться один и тот же шаблон отчета. Язык заголовков или данных выбирает сам пользователь или задается программой.

Такие отчеты востребованы в компаниях, работающих на мировом рынке. К тому же, автоматизация перевода шаблона на разные языки облегчит дальнейшее сопровождение сложных отчетов и избавит от необходимости хранить шаблоны для каждого языка.

Для программистов, использующих генератор отчетов FastReport .NET, создание локализации не составит большого труда.

Итак, какие существуют пути решения данной задачи?

  1. Пользовательское приложение передает в нужном языке заголовки или данные для отчета посредством параметров;
  2. Все поля, которые нужно локализовать, заносятся в базу данных. Каждая строка в таблице будет содержать данные на определенном языке. Отчет использует поля из этой таблицы в заголовках, которые нужно локализовать. Остается только выбрать нужный язык.

Оба варианта имеют свои плюсы и минусы.

В первом случае, с увеличением количества данных, которые нужно локализовать, растет количество кода в пользовательском приложении. Но зато не требуется создание отдельной базы данных или таблицы в существующей. Такой способ больше подойдет для небольшого объема локализуемых данных.

Во втором случае, все данные хранятся в базе, а не в коде пользовательского приложения. Таблицу базы данных удобно масштабировать и добавлять новые данные. Но требуется создание отдельной таблицы, подключения к ней и некоторого количества кода в скрипте отчета. Такой способ больше подойдет для больших объемов локализуемых данных.

Рассмотрим оба предложенных варианта на практике:

Создаем отчет.

1. Для этого сначала нужно создать приложение Windows Forms Application.
2. Теперь добавим на форму компонент Report из вкладки FastReport .NET.
3. Сделаем двойной клик на добавленном компоненте report1. Закрываем форму выбора источника данных. Запускается дизайнер отчетов.
4. Для демонстрации локализации был выбран отчет типа Invoice. Здесь нам потребуется локализовать все заголовки и надписи. Данные о клиенте и товарах будут браться из демонстрационной базы данных (nwind.xml), которая поставляется в комплекте с FastReport .Net.
5. Создаем подключение к базе данных nwind.xml. И выбираем 4 таблицы: Orders, Order Detail, Customers, Products.
6. Чтобы продемонстрировать первый способ локализации, нам потребуется создать ряд параметров отчета.

 Каждый заголовок или надпись в отчете должны быть заменены соответствующими параметрами:

 

 Как видно из рисунка, все заголовки представлены параметрами отчета.

Параметрам можно присвоить значение по умолчанию, на тот случай если вы не хотите передавать некоторые из них. Для этого используется свойство параметра Expression. Текстовое значение задается в двойных кавычках. Например, у параметра pOurCompany значение по умолчанию “Fast Reports Inc.”

7. Для демонстрации второго способа нам потребуется таблица, содержащая те же поля, что и параметры в отчете, а также данные на трех языках.

Воспользуемся, например, базой данных Microsoft Access.

 

Наполняем таблицу данными:

 

  1. Добавим еще один источник данных в отчет. Выбираем созданную в Access базу данных.
  2. Теперь в скрипте отчета необходимо присвоить параметрам отчета значения из полей таблицы Localization. Создаем событие отчета StartReport:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void _StartReport(object sender, EventArgs e)
 {
 string lang =(string)Report.GetParameterValue("pLang");
 DataSourceBase ds=Report.GetDataSource("Localization");
 ds.Init();
 while (ds.HasMoreRows)
 {
 string val=(string)Report.GetColumnValue("Localization.pLang");
 if (val==lang)
 {
Report.SetParameterValue("pInvoice", (string)Report.GetColumnValue("Localization.pInvoice")); Report.SetParameterValue("pOurCompany", (string)Report.GetColumnValue("Localization.pOurCompany")); Report.SetParameterValue("pOurCompanyAddress", (string)Report.GetColumnValue("Localization.pOurCompanyAddress")); Report.SetParameterValue("pOurCompanyPhone", (string)Report.GetColumnValue("Localization.pOurCompanyPhone")); Report.SetParameterValue("pCustomerId", (string)Report.GetColumnValue("Localization.pCustomerId")); Report.SetParameterValue("pCustomerCompany", (string)Report.GetColumnValue("Localization.pCustomerCompany")); Report.SetParameterValue("pCustomerName", (string)Report.GetColumnValue("Localization.pCustomerName")); Report.SetParameterValue("pCustomerAddress", (string)Report.GetColumnValue("Localization.pCustomerAddress")); Report.SetParameterValue("pCustomerPostalCode", (string)Report.GetColumnValue("Localization.pCustomerPostalCode")); Report.SetParameterValue("pCustomerPhone", (string)Report.GetColumnValue("Localization.pCustomerPhone")); Report.SetParameterValue("pCustomerFax", (string)Report.GetColumnValue("Localization.pCustomerFax")); Report.SetParameterValue("pCurrency", (string)Report.GetColumnValue("Localization.pCurrency")); Report.SetParameterValue("pProductName", (string)Report.GetColumnValue("Localization.pProductName")); Report.SetParameterValue("pQuantity", (string)Report.GetColumnValue("Localization.pQuantity")); Report.SetParameterValue("pUnitPrice", (string)Report.GetColumnValue("Localization.pUnitPrice")); Report.SetParameterValue("pAmount", (string)Report.GetColumnValue("Localization.pAmount")); Report.SetParameterValue("pTotal", (string)Report.GetColumnValue("Localization.pTotal")); Report.SetParameterValue("pSignature", (string)Report.GetColumnValue("Localization.pSignature")); Report.SetParameterValue("pName", (string)Report.GetColumnValue("Localization.pName"));
Report.SetParameterValue("pDate", (string)Report.GetColumnValue("Localization.pDate")); 
Report.SetParameterValue("pAgree", (string)Report.GetColumnValue("Localization.pAgree"));
 }
 ds.Next();
 }
 }

 В первой строчке кода мы получаем значение параметра pLang. Забегая вперед, расскажу, что в  этот параметр записывается идентификатор выбранного в программе языка.

Затем получаем источник данных Localization, чтобы в цикле найти запись для выбранного языка.

Далее присваиваем параметрам отчета одноименные значения из таблицы.

Отчет готов. Сохраняем его.

 

Создаем приложение

На форму добавим два переключателя, выпадающий список и пару кнопок.

 

В выпадающий список добавляем 3 языка:

 

Основной код приложения будет вызываться при нажатии кнопки Show report:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using (Report report = new Report())
 {
 report.Load(Environment.CurrentDirectory + "\\Invoice.frx");
 // Here begins the code responsible for the first method of localization
 if ((radioButton1.Checked) && (LanguagesCmdBox.SelectedIndex == 0))
 {
 report.SetParameterValue("pInvoice", "Invoice");
 report.SetParameterValue("pOurCompany", "FastReports Inc");
 report.SetParameterValue("pOurCompanyAddress", "US Alexandria VA 22314");
 report.SetParameterValue("pOurCompanyPhone", "Phone: 800-985-8986");
 report.SetParameterValue("pCustomerId", "Customer Id:");
 report.SetParameterValue("pCustomerCompany", "Company:");
 report.SetParameterValue("pCustomerName", "Name:");
 report.SetParameterValue("pCustomerAddress", "Address:");
 report.SetParameterValue("pCustomerPostalCode", "Postal Code: ");
 report.SetParameterValue("pCustomerPhone", "Phone:");
 report.SetParameterValue("pCustomerFax", "Fax:");
 report.SetParameterValue("pCurrency", "Currency: $");
 report.SetParameterValue("pProductName", "Product Name");
 report.SetParameterValue("pQuantity", "Quantity");
 report.SetParameterValue("pUnitPrice", "Unit Price");
 report.SetParameterValue("pAmount", "Amount");
 report.SetParameterValue("pTotal", "Total");
 report.SetParameterValue("pSignature", "Signature");
 report.SetParameterValue("pName", "Name");
 report.SetParameterValue("pDate", "Date");
 report.SetParameterValue("pAgree", "I declare that the above information is true and correct to the best of my knowledge");
 }
 if ((radioButton1.Checked) && (LanguagesCmdBox.SelectedIndex == 1))
 {
 report.SetParameterValue("pInvoice", "Счет");
 report.SetParameterValue("pOurCompany", "ООО Фаст Репортс");
 report.SetParameterValue("pOurCompanyAddress", "Россия, Ростов-на-Дону");
 report.SetParameterValue("pOurCompanyPhone", "Телефон: +7(863)227-07-40");
 report.SetParameterValue("pCustomerId", "Идентификатор:");
 report.SetParameterValue("pCustomerCompany", "Компания:");
 report.SetParameterValue("pCustomerName", "Имя:");
 report.SetParameterValue("pCustomerAddress", "Адрес:");
 report.SetParameterValue("pCustomerPostalCode", "Индекс:");
 report.SetParameterValue("pCustomerPhone", "Телефон:");
 report.SetParameterValue("pCustomerFax", "Факс:");
 report.SetParameterValue("pCurrency", "Валюта: руб");
 report.SetParameterValue("pProductName", "Наименование");
 report.SetParameterValue("pQuantity", "Количество");
 report.SetParameterValue("pUnitPrice", "Цена");
 report.SetParameterValue("pAmount", "Подитог");
 report.SetParameterValue("pTotal", "Итого");
 report.SetParameterValue("pSignature", "Подпись");
 report.SetParameterValue("pName", "ФИО");
 report.SetParameterValue("pDate", "Дата");
 report.SetParameterValue("pAgree", "Я объявляю, что вышеупомянутая информация верна и правильна насколько я знаю");
 }
 if ((radioButton1.Checked) && (LanguagesCmdBox.SelectedIndex == 2))
 {
 report.SetParameterValue("pInvoice", "Rechnung");
 report.SetParameterValue("pOurCompany", "Fast Reports Inc");
 report.SetParameterValue("pOurCompanyAddress", "US Alexandria VA 22314");
 report.SetParameterValue("pOurCompanyPhone", "Telefon: +4930568373928");
 report.SetParameterValue("pCustomerId", "Kundennummer:");
 report.SetParameterValue("pCustomerCompany", "Unternehmen:");
 report.SetParameterValue("pCustomerName", "Name:");
 report.SetParameterValue("pCustomerAddress", "Anschrift:");
 report.SetParameterValue("pCustomerPostalCode", "Postleitzahl:");
 report.SetParameterValue("pCustomerPhone", "Telefon:");
 report.SetParameterValue("pCustomerFax", "Faxen:");
 report.SetParameterValue("pCurrency", "Währung: eur");
 report.SetParameterValue("pProductName", "Produktname");
 report.SetParameterValue("pQuantity", "Menge");
 report.SetParameterValue("pUnitPrice", "Stückpreis");
 report.SetParameterValue("pAmount", "Höhe");
 report.SetParameterValue("pTotal", "Gesamt");
 report.SetParameterValue("pSignature", "Signatur");
 report.SetParameterValue("pName", "Name");
 report.SetParameterValue("pDate", "Datum");
 report.SetParameterValue("pAgree", "Ich erkläre, dass die oben genannten Informationen wahr und korrekt auf die nach meinem besten Wissen")
 }
 // Here begins the code responsible for the second method of localization
 if (radioButton2.Checked)
 {
 switch (LanguagesCmdBox.SelectedIndex)
 {
 case 0:
 report.SetParameterValue("pLang", "En");
 break;
 case 1:
 report.SetParameterValue("pLang", "Ru");
 break;
 case 2:
 report.SetParameterValue("pLang", "De");
 break;
 }
 }
 

  Рассмотрим код подробнее. Как видим, он разбит комментариями на два блока - первый способ и второй способ локализации. Вначале загружается разработанный нами ранее отчет.

Далее проверяется, выбран ли первый способ локализации и какой язык задан в выпадающем списке. Три условных конструкции для трех языков. Внутри каждого условия происходит присвоение значений параметрам отчета. В методе SetParameterValue два параметра: имя параметра отчета и его значение. Таким образом, мы  заполняем все параметры значениями на выбранном языке.

Для второго способа локализации используются аналогичные условные конструкции. Но внутри задается лишь один параметр отчета – pLang – выбранный язык. Получив этот параметр, отчет выберет нужную запись из таблицы локализации.

Есть еще одно преимущество данного способа, о котором не было сказано в начале. Базу данных с локализациями (Localization) можно сделать хранимой внутри отчета для упрощения его последующего сопровождения и исключения дополнительного источника данных. Для этого в отчете нужно выбрать таблицу Localization в дереве данных и указать свойство StoreData = True. Таблица будет сохранена в шаблоне отчета. В таком случае можно будет пропустить настройку одной из баз в программе. Однако, есть одно неудобство использования хранимой базы данных (таблицы) - при добавлении новых полей нужно будет восстановить подключение к исходной таблице.

Итак, мы рассмотрели два способа локализации отчета в FastReport .Net. Какой из способов лучше - решать разработчику, это зависит от конкретного случая. Далее будут приведены результаты проделанной работы – три отчета на разных языках.

На английском языке:

 

На русском:

 

И немецком: