Skip to main content Skip to footer

How to localize the Web Designer

Background:

This article shows you how to localize the web designer.

Steps to Complete:

Below provides information on how to set up Web Designer.

Code Snippets

General

<!DOCTYPE html>
<html lang="en">

<head>

	<title>ActiveReports Web Designer</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<meta http-equiv="x-ua-compatible" content="ie=edge">

	<!-- Mandatory -->
	<link rel="stylesheet" href="vendor/css/materialdesignicons.min.css" media="all" type="text/css" />
	<link rel="stylesheet" href="vendor/css/bootstrap.min.css" />
	<link rel="stylesheet" href="vendor/css/font-awesome.min.css">
	<link rel="stylesheet" href="vendor/css/ionicons.min.css">
	<link rel="stylesheet" href="vendor/css/fonts-googleapis.css" type="text/css">
	<!--------------->

	<!-- Optional: Open-Report/Save-Report-As Dialogs -->
	<link rel="stylesheet" href="file-dialog.css" />

	<!-- Optional: Preview Report -->
	<link rel="stylesheet" href="viewer-container.css" type="text/css">

	<!-- Optional: Add Data Sets using Data Set Picker -->
	<link rel="stylesheet" href="data-set-picker.css" />

	<!-- Optional: File View -->
	<link rel="stylesheet" href="file-view.css" />

	<!-- Optional: Add/Edit Data Sources using Data Source Editor -->
	<link rel="stylesheet" href="ar-datasource-editor.css" />

	<!-- Mandatory -->
	<link rel="stylesheet" href="web-designer.css" />

</head>

<body>

	<!-- Mandatory -->
	<script src="vendor/js/jquery.js"></script>
	<script src="vendor/js/bootstrap.min.js"></script>
	<!--------------->

	<!-- Optional: Open-Report/Save-Report-As Dialogs -->
	<script src="file-dialog.js"></script>

	<!-- Optional - Preview Report -->
	<script src="viewer-container.js"></script>

	<!-- Optional: Add Data Sets using Data Set Picker -->
	<script src="data-set-picker.js"></script>

	<!-- Optional: File View -->
	<script src="file-view.js"></script>

	<!-- Optional: Add/Edit Data Sources using Data Source Editor -->
	<script src="ar-datasource-editor.js"></script>

	<!-- Mandatory -->
	<script src="baseServerApi.js"></script>
	<script src="web-designer.js"></script>
	<!--------------->

	<!-- Mandatory -->
	<div id="designer-id" style="width: 100%; height: 100%;"></div>

	<!-- Optional: File View -->
	<div id="file-view-id" style="width: 100%; height: 100%; display: none;"></div>

	<!-- Optional - Preview Report -->
	<div id="viewer-container-id" style="width: 100%; height: 100%; display: none;"></div>

	<!-- Optional: Save-Report-As Dialog -->
	<div id="save-as-dialog-id" style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;display: none;z-index: 9999;"></div>

	<!-- Optional: Open-Report Dialog -->
	<div id="open-dialog-id" style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;display: none;z-index: 9999;"></div>

	<!-- Optional: Add Data Sets using Data Set Picker -->
	<div id="data-set-picker-dialog-id" style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;display: none;z-index: 9999;background-color: #dedede;"></div>

	<!-- Optional: Add/Edit Data Sources using Data Source Editor -->
	<div id="data-source-editor-dialog-id"></div>

	<script>

		var designerId = 'designer-id';
		var viewerContainerId = 'viewer-container-id';
		var fileViewId = 'file-view-id';
		var saveAsDialogId = 'save-as-dialog-id';
		var openDialogId = 'open-dialog-id';
		var dataSetPickerDialogId = 'data-set-picker-dialog-id';
		var dataSourceEditorDialogId = 'data-source-editor-dialog-id';

		/* Implementation Details - See the section below. */

		/* Mandatory: Create Designer Options */
		var designerOptions = GrapeCity.ActiveReports.WebDesigner.createDesignerOptions(baseServerApi);

		/* Optional: Save Report */
		designerOptions.saveButton.visible = true;
		designerOptions.onSave = onSaveImpl;

		/* Optional: Save Report As */
		designerOptions.saveAsButton.visible = true;
		designerOptions.onSaveAs = onSaveAsImpl;

		/* Optional: Open Report */
		designerOptions.openButton.visible = true;
		designerOptions.onOpen = onOpenImpl;

		/* Optional: File View */
		designerOptions.openFileView = openFileViewImpl;

		/* Optional: Preview Report */
		designerOptions.openViewer = openViewerImpl;

		/* Optional: Add/Edit/Remove Data Sets */
		designerOptions.dataTab.dataSets.canModify = true;

		/* Optional: Add Data Sets using Data Set Picker */
		designerOptions.dataSetPicker.open = openDataSetPickerImpl;
		designerOptions.dataSetPicker.close = closeDataSetPickerImpl;

		/* Optional: Add/Edit/Remove Data Sources */
		designerOptions.dataTab.dataSources.canModify = true;

		/* Optional: Add/Edit Data Sources using Data Source Editor */
		ARDataSourceEditor.init(dataSourceEditorDialogId);
		designerOptions.openDataSourceEditor = openDataSourceEditorImpl;

		/* Mandatory: Render Designer Application */
		GrapeCity.ActiveReports.WebDesigner.renderApplication(designerId, designerOptions);

	</script>

</body>

</html>

Implementation Details

Supplementary Functions

var dialogs = [
	saveAsDialogId, openDialogId,
	dataSetPickerDialogId, dataSourceEditorDialogId,
];

var showElement = function (id) {
	if (!id) return;
	($('#' + id)).css('display', 'block');
};

var hideElement = function (id) {
	if (!id) return;
	($('#' + id)).css('display', 'none');
};

var hideDialogs = function () {
	dialogs.forEach(hideElement);
}

var showDesigner = function () {
	var info = GrapeCity.ActiveReports.WebDesigner.api.getReportInfo();
	var isDirty = GrapeCity.ActiveReports.WebDesigner.api.isReportDirty();
	document.title = info.name + (isDirty ? ' *' : '');
	showElement(designerId);
	GrapeCity.ActiveReports.WebDesigner.focus();
};

var makeOptions = function (baseOptions, additionalOptions) {
	return $.extend({}, baseOptions || {}, additionalOptions || {});
}

On Save Implementation

/* Optional: Save Report */
var onSaveImpl = function (options) {
	baseServerApi
		.saveExistingReport({ id: options.reportInfo.id, content: options.reportInfo.content })
		.then(function (saveResult) {
			options.onSuccess({
				id: saveResult.Id,
				name: options.reportInfo.name
			});
		});
};

On Save Implementation

/* Optional: Save Report As */
var onSaveAsImpl = function (options) {
	showElement(saveAsDialogId);

	fileDialog.createSaveReportAsDialog(saveAsDialogId, {
		locale: options.locale,

		api: {
			getReportsList: function () {
				return baseServerApi.getReportsList().then(function (reportsList) {
					return reportsList.map(function (reportInfo) {
						return { path: reportInfo.Name };
					});
				});
			},
			saveReport: function (saveOptions) {
				return baseServerApi.saveNewReport({ name: saveOptions.path, content: options.reportInfo.content }).then(function (saveResult) {
					return { id: saveResult.Id };
				});
			},
		},
		reportInfo: {
			path: options.reportInfo.name,
		},
		onSuccess: function (saveResult) {
			hideElement(saveAsDialogId);
			options.onSuccess({ id: saveResult.id, name: saveResult.path });
		},
		onClose: function () {
			hideElement(saveAsDialogId);
			showDesigner();
		},
	});
};

On Open Implementation

/* Optional: Open Report */
var onOpenImpl = function (options) {
	showElement(openDialogId);
	var loadedReportList = null;

	fileDialog.createOpenReportDialog(openDialogId, {
		locale: options.locale,

		api: {
			getReportsList: function () {
				return baseServerApi.getReportsList().then(function (reportsList) {
					loadedReportList = reportsList;
					return reportsList.map(function (reportInfo) {
						return { path: reportInfo.Name };
					});
				});
			},
			openReport: function (openOptions) {
				return new $.Deferred(function (def) {
					var reportInfo = (loadedReportList || []).find(function (r) {
						return r.Name === openOptions.path;
					});
					if (!reportInfo) return def.reject();

					GrapeCity.ActiveReports.WebDesigner.api.openReport({
						reportInfo: {
							id: reportInfo._id,
							name: reportInfo.Name,
							permissions: ['all'],
						},
						onFinish: function () {
							def.resolve({ id: reportInfo._id });
						},
					});
				});
			},
		},
		onSuccess: function (openResult) {
			hideElement(openDialogId);
		},
		onClose: function () {
			hideElement(openDialogId);
			showDesigner();
		},
	});
};

Open File View Implementation

/* Optional: File View */
var openFileViewImpl = function (options) {
	hideElement(designerId);
	showElement(fileViewId);

	var fileViewOptions = makeOptions(options, {
		onClose: function () {
			if (options.onClose) options.onClose();
			hideElement(fileViewId);
			showDesigner();
		},
		serverApi: {
			getReportsList: baseServerApi.getReportsList,
			getReportRevisions: baseServerApi.getReportRevisions,
			getDataSetsList: baseServerApi.getDataSetsList,
			getTemplatesList: baseServerApi.getTemplatesList,
			getTemplateContent: baseServerApi.getTemplateContent,
			getTemplateThumbnail: baseServerApi.getTemplateThumbnail,
		},
		createReport: GrapeCity.ActiveReports.WebDesigner.api.createReport,
		openReport: GrapeCity.ActiveReports.WebDesigner.api.openReport,
		saveReport: GrapeCity.ActiveReports.WebDesigner.api.saveReport,

		ignoreCase: true,
		delimiter: '/',
	});

	fileView.renderFileView(fileViewId, fileViewOptions);
};

Open Viewer Implementation

/* Optional: Preview Report */
var openViewerImpl = function (options) {
	hideElement(designerId);
	showElement(viewerContainerId);

	var viewerContainerOptions = makeOptions(options, {
		makeViewerUrl: function () {
			var baseUrl = '<http://localhost:58723/preview/';>
			var reportId = encodeURIComponent(options.reportInfo.id);
			var language = options.locale;
			return baseUrl + reportId + '?lng=' + language;
		},
	});
	viewerContainer.renderViewerContainer(viewerContainerId, viewerContainerOptions, function () {
		var isTemporaryReport = options.reportInfo.isTemporary;
		if (isTemporaryReport) {
			var reportId = options.reportInfo.id;
			baseServerApi.deleteTemporaryReport({ id: reportId });
		}
		hideElement(viewerContainerId);
		showDesigner();
	});
};

Open/Close Data Set Picker Implementation

/* Optional: Add Data Sets using Data Set Picker */
var openDataSetPickerImpl = function (options) {
	var openInPanel = options.mode === 'Panel';
	if (!openInPanel) {
		hideDialogs();
		showElement(dataSetPickerDialogId);
	}
	dataSetPicker.renderDataSetPicker(openInPanel ? options.elementId : dataSetPickerDialogId, makeOptions(options, {
		serverApi: {
			getDataSetsList: baseServerApi.getDataSetsList,
			getDataSourcesAndDataSets: baseServerApi.getDataSourcesAndDataSets,
		},
		onClose: function () {
			options.onClose();
			if (!openInPanel) hideElement(dataSetPickerDialogId);
			dataSetPicker.dispose();
		}
	}));
};
var closeDataSetPickerImpl = function () {
	dataSetPicker.dispose();
};

Open Data Source Editor Implementation

/* Optional: Add/Edit Data Sources using Data Source Editor */
var openDataSourceEditorImpl = function (options) {
	ARDataSourceEditor.open(makeOptions(options, {
		serverApi: {
			testConnection: baseServerApi.testDataSourceConnection,
		},
	}));
};

Custom Localization

Basic Sample Custom Localization JSON

Here data-set-picker-custom-localization.json is used as a basic sample custom-localization.json.

  • "ns" property is a namespace – it shouldn't be translated - it is required for proper work of the Custom Localization feature

  • "lng" property is a locale - it should be replaced with a proper locale - for example, "es" for Spanish

  • "resources" property contains localization resources used in the corresponding namespace - contents of this property require translation

[
	{
		"ns": "data-set-picker",
		"lng": "<custom-locale>",
		"resources": {
			"buttons": {
				"add": "Add",
				"cancel": "Cancel"
			},
			"gettingContent": "Getting resource content...",
			"gettingDataResources": "Getting list of available data resources...",
			"header": "Pick a Data Set",
			"nameTemplates": {
				"dataSet": "DataSet",
				"dataSource": "DataSource"
			},
			"noDataResourcesAvailable": "No data resources available",
			"searchBoxPlaceholder": "enter data resource name here..."
		}
	}
]

Common

If you would like to utilize the Custom Localization feature:

  1. You need to translate the resources sections from custom-localization.json files.

  2. Also it is required to replace custom-locale stub with your locale.

  3. Pass the translated custom-localization.json contents to the localeData property of the corresponding options.

Example:

var options = {
	localeData: [
		{
			"ns": "data-set-picker",
			"lng": "es",
			"resources": {
				"buttons": {
					"add": "Agregar",
					"cancel": "Cancelar"
				},
				// ... other translated localization resources
			}
		}
	],
	// ... other Data Set Picker options
};

dataSetPicker.renderDataSetPicker('data-set-picker-id', options);

Name Templates

In designer-custom-localization.json and data-set-picker-custom-localization.json "resources" sections there are "nameTemplates" sub-sections. Values in these sections are expected to be alphanumeric identifiers. I.e., they can contain only letters and digits but cannot start with a digit. The same is applicable to "dataSourceNameTemplate" property from data-source-editor-custom-localization.json "resources" section.

Parameters

Please note some resource strings have parameters - they are in curly braces {} - you don't need to translate parameter labels:

"versionLabel": "Version: {versionNumber}"
/* {versionNumber} is a parameter - it doesn't require translation - only text is translated */
"versionLabel": "Versión: {versionNumber}"

Resources:

https://global-cdn.grapecity.com/kb/activereports/ard/webDesigner_docs.zip

Evan Warren