Table of Contents

How to Work with Perspectives and Translations

Perspectives control which objects are visible in specific client views. Translations (cultures) provide localized names, descriptions and display folders. Both use indexer properties on TOM objects. See How to Navigate the TOM Object Hierarchy for details on accessing TOM objects and their indexers.

Quick reference

// Perspectives
measure.InPerspective["Sales"] = true;              // include in perspective
measure.InPerspective["Sales"] = false;             // exclude from perspective
var isIn = measure.InPerspective["Sales"];           // check membership

// Translations
measure.TranslatedNames["da-DK"] = "Omsætning";    // set translated name
measure.TranslatedDescriptions["da-DK"] = "...";    // set translated description
measure.TranslatedDisplayFolders["da-DK"] = "Salg"; // set translated folder

var name = measure.TranslatedNames["da-DK"];     // read translation (empty string if unset)

// Iterate cultures
foreach (var culture in Model.Cultures)
    Info(culture.Name);                              // "da-DK", "de-DE", etc.

Setting perspective membership

The InPerspective indexer is available on tables, columns, measures and hierarchies (any (xref:TabularEditor.TOMWrapper.ITabularPerspectiveObject)).

// Add all measures in a table to a perspective
Model.Tables["Sales"].Measures.ForEach(m => m.InPerspective["Sales Report"] = true);

// Remove a table and its children from a perspective
var table = Model.Tables["Internal"];
table.InPerspective["Sales Report"] = false;

Copying perspective membership

Copy the perspective visibility from one object to another.

var source = Model.AllMeasures.First(m => m.Name == "Revenue");
var target = Model.AllMeasures.First(m => m.Name == "Revenue YTD");

foreach (var p in Model.Perspectives)
    target.InPerspective[p.Name] = source.InPerspective[p.Name];

Creating and removing perspectives

// Create a new perspective (empty upon creation -- add objects as shown above)
var p = Model.AddPerspective("Executive Dashboard");

// Remove a perspective
Model.Perspectives["Old View"].Delete();

Setting translations

Translation indexers are available on objects implementing (xref:TabularEditor.TOMWrapper.ITranslatableObject) (tables, columns, measures, hierarchies, levels). Display folder translations require (xref:TabularEditor.TOMWrapper.IFolderObject) (measures, columns, hierarchies).

var m = Model.AllMeasures.First(m => m.Name == "Revenue");
m.TranslatedNames["da-DK"] = "Omsætning";
m.TranslatedDescriptions["da-DK"] = "Total omsætning i DKK";
m.TranslatedDisplayFolders["da-DK"] = "Salg";

Finding missing translations

foreach (var culture in Model.Cultures)
{
    var missing = Model.AllMeasures
        .Where(m => string.IsNullOrEmpty(m.TranslatedNames[culture.Name]));

    Info($"{culture.Name}: {missing.Count()} measures without translated names");
}

Bulk-setting translations from a naming convention

// Copy the default name as the translation for cultures that are missing it
foreach (var culture in Model.Cultures)
{
    Model.AllMeasures
        .Where(m => string.IsNullOrEmpty(m.TranslatedNames[culture.Name]))
        .ForEach(m => m.TranslatedNames[culture.Name] = m.Name);
}

Creating and removing cultures

// Add a new culture
var culture = Model.AddTranslation("fr-FR");

// Remove a culture
Model.Cultures["fr-FR"].Delete();

Dynamic LINQ equivalent

In BPA rule expressions, perspective and translation indexers are accessed directly.

C# script Dynamic LINQ (BPA)
m.InPerspective["Sales"] InPerspective["Sales"]
!m.InPerspective["Sales"] not InPerspective["Sales"]
string.IsNullOrEmpty(m.TranslatedNames["da-DK"]) String.IsNullOrEmpty(TranslatedNames["da-DK"])

See also