Kine's Info

What I found and what I know about Microsoft Dynamics NAV

NAV Profile madness

Time to write article about my last two work days. As each time, when some challenge appears, I learn a lot. This time it applies too. Last days I had a problems with the Profiles in NAV and what they are storing.

1) Translations and Profiles

If you need add new language to the Microsoft Dynamic NAV, it is not just about adding the translated captions to the objects. Even when you translate all in objects, you can still hit non-translated labels on the interface, because the profile stored CaptionML in the delta XML too. And there is first problem – how to "correct" the profile. Of course, you can go and overwrite the things through the Windows Client and the page configuration. But, if there are thousands of the CaptionML to translate? (in my case there were 633 unique strings to translate, many of them on many places and multiple profiles). Example of the part of delta XML:

<Node name="Actions" uri="urn:schemas-microsoft-com:dynamics:NAV:MetaObjects" id="fcfc72f4-831c-4cf9-b0f8-c1782cbe1858">
  <Nodes>
    <
Node name="Trigger" uri="urn:schemas-microsoft-com:dynamics:NAV:MetaObjects"> 
  <Nodes />
  <Attributes>
    <Attribute value="OnAction" name="TriggerType" uri="" />
    <Attribute value="a60Action32a62_a45_OnAction" name="Name" uri="" /> 
  </Attributes> 
</Node>
</Nodes>
<Attributes>
  <Attribute value="ActionDefinition" name="xsi:type" uri="http://www.w3.org/2001/XMLSchema-instance" />
  <Attribute value="-101" name="ID" uri="" />
  <Attribute value="Action32" name="Name" uri="" />
  <Attribute value="Stornovat žurnál" name="Caption" uri="" />
  <Attribute value="ENU=Reverse Register;CSY=Stornovat žurnál;SKY=Stornovať žurnál" name="CaptionML" uri="" />
  <Attribute value="True" name="Visible" uri="" />
  <Attribute value="fcfc72f4-831c-4cf9-b0f8-c1782cbe1858" name="ControlGUID" uri="" />
  <Attribute value="ReverseRegister" name="Image" uri="" />
  <Attribute value="true" name="Ellipsis" uri="" />
  <Attribute value="Edit" name="RunPageMode" uri="" />
  <Attribute value="Process" name="PromotedCategory" uri="" /> 
</Attributes>
</Node>


What you can do to automate the thing? Waldo will be happy with this: PowerShell

The profile is stored as an XML in the BLOB field in table [Profile Metadata]. You can read it through powershell, find what you want (all attributes with name CaptionML) and replace the value with correct one. BUT: the BLOB field is compressed. How you can read/write the value from PowerShell?

Yes, another challenge. Will be described in separate article… ;-)

Result

I have created two PowerShell scripts. First, Export-NAVProfileCaptionsML.ps1, will read the Profile Metadata and return list of objects having properties "value" and "newvalue". Value is the "original" CaptionML string in form e.g. "ENU=E&ntries;CSY=Po&ložky". You can save this into CSV, make "newvalue" to be e.g. "ENU=E&ntries;CSY=Po&ložky;SKY=Po&ložky".

Example of usage:

Export-NAVProfileCaptionML.ps1 -Server localhost -Database mydb -Filter MYPROFILE | Export-Csv -Path ToTranslate.csv

###translate the ToTranslate.csv in e.g. excel without messing the structure of the header###

Import-Csv -Path ToTranslate.csv | Translate-NAVProfileCaptionML.ps1 -Server localhost -Database mydb -Filter MYPROFILE

After you have translations, you can use second script, Translate-NAVProfileCaptionsML.ps1 and feed it with the array of objects having properties "value" and "newvalue" (you can read it from CSV). It will go through the profiles, search for the CaptionML attributes and if matching "value" is found, it is replaced with "newvalue" and whole XML is stored back to the NAV Blob.

 

You can find the scripts here: "NAV PowerShell Scripts and TFS Build Templates" on Codeplex

   

2) Action trigger names and Profiles

After I have solved the translations, I returned back to older issue we had. Users were sometime experiencing errors when clicking on some action on page like:

"Method 'Page116.a60Action32a62_a45_OnAction' not found."

Quick look at the page definition shows us, that the Action32 is not named Action32, but ReverseRegister. Thus the trigger name is different now. Ok, why the NAV client wants to call trigger, with wrong name? Of course, again, the profile. In the XML of the profile, you can find sections like in previous example.

As you can see, there is Attribute saving the action name. Why??? Do not know… may be I even do not want to know…

Ok, what we can do with this? Again, PowerShell script. But, how to find correct trigger name? Hmm… [Object Metadata].[Metadata] for this object looks like this:

<ActionContainers xsi:type="ActionContainerDefinition" ActionContainerType="ActionItems">
  <Actions xsi:type="ActionGroupDefinition" ID="31" CaptionML="CSY=F&amp;unkce;ENU=F&amp;unctions;SKY=F&amp;unkcie" ControlGUID="{00000074-0000-001F-0008-0000836BD2D2}" Image="Action">
    <Actions xsi:type="ActionDefinition" ID="32" Name="ReverseRegister" CaptionML="CSY=Stornovat žurnál;ENU=Reverse Register;SKY=Stornovať žurnál" ControlGUID="{00000074-0000-0020-0008-0000836BD2D2}" Image="ReverseRegister" Ellipsis="1" RunPageMode="Edit" RunObjectSrcTable="0" Promoted="1" PromotedCategory="Process">
      <Trigger TriggerType="OnAction" Name="ReverseRegister_a45_OnAction"/>
    </Actions>
  </Actions>
</ActionContainers>


Super! We have a trigger name here. But… another problem on the way – how to "connect" these two things together. We have action ID attribute in the Object Metadata, but Action name in the Profile Metadata and no simple ID. But, name is just ID with "Action" on beginning. Lets remove it and take the ID from there… this was simple.

Result

Another PowerShell script, which reads the Profile Metadata, loop all triggers in the XML, than reads the Object Metadata for the page, tries to find the corresponding trigger name and if it does not exists, it fill find it based on the Action ID and correct it. We already have needed functions to read NAV Blob data from PowerShell, thus not hard to create the script. You can find the script under name Fix-NAVProfileTriggerNames.ps1 in the project "NAV PowerShell Scripts and TFS Build Templates" on Codeplex.

 

Conclusion

Profiles are big pain sometime, because they are storing things which could change and you do not have a simple way to correct it. But thanks to PowerShell, it could be fixed.

P.S.: The script sources are updated on the Codeplex when needed, I recommend to follow the project and keep eye on the updates…  

 

  • Hi Kine,

    thanks for sharing this. But it leaves me bewildered. What else is this than a big clusterfsck? WTF is a NAV profile and

    why do I have to change things there?

    with best regards

    Jens

  • Profiles are the core of the "Role Tailoring". It is the difference between classic client with "all is same for everyone" and the new 3-tier architecture with "Role-Tailored clients", with "you can see what you need" based on the profile you have assigned... And there are pre-configured profiles in the system and if you configure some or change something on page what is configured in some profile, it will lead to these problems. It means, if you want to use fully the RTC (Role-tailored clients), you need to work with profiles and prepare the environment for different roles of the users in company.

  • Hi Kine,

    thank you for the answers. IOW, role tailoring doesn't come with the tools to tailor the roles? Strange concept... Whatever happended to C/AL objects? Shouldn't they be enough to actually set up a NAV system?

    with best regards

    Jens

  • The tools are there. You just run the Client in Configuration mode (runtime parameter). Than what you do on the page (hide field, move action etc.) will be saved not to the user settings, but to the profile.

    But in background, more than that is saved into the profile, and sometime it can create problems. I think it is not End-user problems in most cases (end-user is working with mostly one language, doing the configuration on stable system). But this is rather Partner's problem, which is creating profile over database under development, where actions could be renamed, or you need to add new language layer to existing profiles for new customers in new countries etc.

  • Hi Kine,

    Thanks for your very useful script.

    I am currently working on translation as well, and I am looking for a way to get the CapionML of the action from a page... to be able to quickly look at standard translation for the "new value" column ;-)

    Could you just give me a clew, please?

    I tries by the "Object" SQL table, but I do not succeed to get the metadata...

    Thanks for your help.

    Julien

  • You can use the NAV Model tools (powershell scripts for work with the objects) to export the selected object, export the translation file for it. Than in this file, you can find the original and the translation for it (because it will have same code, only different language number). You can script all this... ;-)