<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>en-us</language>
    <title>Tiki RSS feed for forum: Multi-Language Add-In for Visual Studio</title>
    <description>Latest posts to this formQuestions about the Multi-Language Add-In for Visual Studio .NET</description>
    <image>
      <url>https://www.jollans.de/tiki/img/tiki/Tiki_WCG.png</url>
      <title>Feed logo</title>
      <link>https://www.jollans.de/tiki/</link>
    </image>
    <pubDate>Sun, 05 Apr 2026 17:52:22 +0000</pubDate>
    <generator>Laminas_Feed_Writer 2 (https://getlaminas.org)</generator>
    <link>https://www.jollans.de/tiki/</link>
    <atom:link rel="self" type="application/rss+xml" href="https://www.jollans.de/tiki/tiki-forum_rss.php?forumId=1"/>
    <item>
      <title>Hiding texts in XAML files</title>
      <description><![CDATA[Back in Version 6.03 I made a significant change to the handling of texts in XAML files, using a new markup extension, for example:
%%%
{CODE(caption="XAML Localization with m:Lang" wrap="0" theme="default")}
Content="{m:Lang Apply}"
{CODE}

This is described in the forum page [https://jollans.com/tiki/tiki-view_forum_thread.php?tiki-view_forum_thread.php?forumId=1&comments_parentId=1160#threadId1160|XAML Localization with a markup extension]

Now I have made another significant change, this time related to hiding texts in XAML files.

When you hide an attribute, Multi-Language will now insert the attached property%%%
{CODE(caption="XAML" wrap="0" theme="default")}
m:Hide.Option="node"
{CODE}
for example 

{CODE(caption="XAML" wrap="0" theme="default")}
<TextBlock Text="Three" m:Hide.Option="node" />
{CODE}

That is all that is required to hide the texts in this XAML node.

This is a big simplification. Previously Multi-Language added the x:Uid attribute to identify the XAML node. It then stored the fact that a property was hidden in the project database.

In the new version, Multi-Language does not add x:Uid or x:Name to a node either when you hide it, or when you select it for translation. In addition, Multi-Language stores nothing related to the node in the project database.

The attached property m:Hide.Option is defined in the file MlExtension.cs/.vb along with the markup extension used to fetch translated texts. The definition is extremely minimal.

{CODE(caption="C#" wrap="0" theme="default")}
public enum HideOption { node, tree, none }

public static class Hide
{
  public static HideOption GetOption ( Object obj )
  {
    return HideOption.node ;
  }
  public static void SetOption ( Object obj, HideOption value )
  {
  }
}
{CODE}

===The property value is not stored at all.=== In particular, it is not a dependency property, and it may be applied to objects which are not dependency objects.

As a result, the property can be applied almost anywhere.

For example on a setter

{CODE(caption="XAML" wrap="0" theme="default")}
<st<x>yle x:Key="TBStyle" TargetType="TextBlock">
  <Setter Property="FontFamily"   Value="Courier New" m:Hide.Option="node" />
  <Setter Property="FontStyle"    Value="Italic"      m:Hide.Option="node" />
  <Setter Property="TextWrapping" Value="Wrap"        m:Hide.Option="node" />
  <Setter Property="FontSize"     Value="12" />
</Style>
{CODE}

!!!!Alternativ usage m:Hide.Option="tree"

In the previous example, it would be more convenient to hide the properties at a higher level, for the whole style.

This is possible using the alternative value __m:Hide.Option="tree"__.

{CODE(caption="XAML" wrap="0" theme="default")}
<st<x>yle x:Key="TBStyle" TargetType="TextBlock" m:Hide.Option="tree">
  <Setter Property="FontFamily"   Value="Courier New" />
  <Setter Property="FontStyle"    Value="Italic"      />
  <Setter Property="TextWrapping" Value="Wrap"        />
  <Setter Property="FontSize"     Value="12" />
</Style>
{CODE}

This option would effectively mark the style node ===and all its child nodes as hidden===.

__Note:__%%%Multi-Language recognizes this option, but there is no GUI support for inserting it. If you want to use this option, you must add it by hand.

You cannot apply the option directly to a Resources node, but if you place your resources within a resource dictionary, you can apply it to the resource dictionary. So you could effectively hide all strings in your resources in the following way.

{CODE(caption="XAML" wrap="0" theme="default")}
<Window.Resources>
  <ResourceDictionary m:Hide.Option="tree">

  </ResourceDictionary>
</Window.Resources>
{CODE}

Finally, if you wanted to revert the __m:Hide.Option="tree"__ at a lower level in the tree structure, this is possible with __m:Hide.Option="none"__.]]></description>
      <pubDate>Sun, 26 Apr 2020 17:20:30 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1163</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1163</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Performing a partial scan</title>
      <description><![CDATA[This topic is part of a response to a question on the [https://marketplace.visualstudio.com/items?itemName=PhilJollans.Multi-LanguageforVisualStudio|Visual Studio Marketplace] (which doesn't support adding screen shots!)

For what it is worth, there is a way to perform a partial scan.

First select the project from the drop down list of projects.

{img src="img/wiki_up/scan_subset_1.png" }

For a new project there will be dialog to select the original language of the project. After that there is a dialog where you can select some scan options. If this dialog does not appear, see the note at the end of this page.

In this dialog, select "Do not initialise" for both Controls and Source Code.

{img src="img/wiki_up/scan_subset_2.png" }

After that you can open the menu on the first button on the toolbar and select the command "Rescan selected components".

{img src="img/wiki_up/scan_subset_3.png" }

This brings up a list of the components in the project. You can select a subset of the components. When you click on OK, only these components are scanned.

{img src="img/wiki_up/scan_subset_4.png" }

If the dialog with rescan options does not appear, you may need to select the option "Show scan options dialog" via the Visual Studio Options:

{img src="img/wiki_up/scan_subset_5.png" }

Phil]]></description>
      <pubDate>Tue, 21 Apr 2020 21:12:08 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1162</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1162</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>New Version for Visual Studio 2019</title>
      <description><![CDATA[I have made a new version of Multi-Language for Visual Studio 2019.

This is currently version 7.01.0004. It can be downloaded with the link%%%--http://www.jollans.com/MultiLanguageWPF.vsix--%%%[http://www.jollans.com/MultiLanguage2019.vsix]

This version contains two major changes:
---
1. A new code scan for C# and VB.NET based on Roslyn, the .NET compiler platform.

There are two aspects to this:
*Using Roslyn to detect strings in the source code
*Using Roslyn to make changes to the source code
I was going to introduce this support as version 7.00.
---
2. A new implementation of the tool window using WPF

Many users have reported, that the Multi-Language window remained blank in Visual Studio 2019. I think it worked correctly in the first release, but has stopped working with later updates.

In all previous versions, the tool window was implemented as a WinForms control.

I have fixed the UI problems in Visual Studio 2019 by implementing a new top level control using WPF. This includes the toolbar, drop-down project list and the tab control. However, the three grids are still implemented in WinForms and hosted in WindowsFormsHost controls.

Obviously, I would like to migrate the grids to WPF (and to an MVVM structure) as well, but this will be substantially more work.

At the same time, I have split the implementation into separate DLLs so, for example, the top level Visual Studio Package and Tool Window are separate from the bulk of the previous implementation.
---
Since the previous version is not working at all in Visual Studio 2019, I have decided that the current version is good enough to be released.

However, I am still working on it, and I am sure that there will be multiple updates in the coming months.

Phil]]></description>
      <pubDate>Thu, 15 Aug 2019 22:55:26 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1161</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1161</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>XAML Localization with a markup extension</title>
      <description><![CDATA[In previous versions of Multi-Language, localization of XAML files was implemeted using the markup extension x:Static, for example:
%%%
{CODE(caption="XAML Localization with x:Static" wrap="0" theme="default")}
Content="{x:Static res:Resources.Apply}"
{CODE}

Language switching at run time was  implemeted - identically to Windows Forms projects - by generating a function named __ml_UpdateControls__ and calling it from an event handler.

This does not work if you try to localize a string in a DataTemplate in XAML. In this case, Multi-Language would generate code in the function __ml_UpdateControls__ which would not compile.

Changing the text in a DataTemplate at run time is difficult problem. The whole idea of a template is that it may be instantiated multiple times. If you want to change it at run time, then you have to update each place where the template is used.

This is probably not possible in a simple function like __ml_UpdateControls__.
---
Starting with version 6.03, I have made a significant change to the localization in XAML files.

Multi-Language now adds a new file to the project, called __MLExtension.cs__ or __MLExtension.vb__, which contains a markup extension named __LangExtension__ in the namespace __MultiLanguageMarkup__.

In each XAML file, Multi-Language adds a namespace definition:
%%%
{CODE(caption="Namespace definition")}
xm<x>lns:m="clr-namespace:MultiLanguageMarkup"
{CODE}

Texts are now localized using the new markup extension, for example:
%%%
{CODE(caption="XAML Localization with m:Lang" wrap="0" theme="default")}
Content="{m:Lang Apply}"
{CODE}

This instantiates the markup extension __LangExtension__ and passes the name of the resource as a parameter to its constructor.

===Switching the language at run time is handled in the markup extension===.

The markup extension maintains a list of all the places where it is used. In most cases this list will contain one item, but if the markup extension is used in a DataTemplate, then it will contain one item for each time the template is used.

The markup extension is added to your project as a source file, so you can read how it works if it interests you. I have tried to keep it as simple as possible, while doing the necessary work, and provided plenty of comments.

Because language switching is now handled in the markup extension, the function __ml_UpdateControls__ is not necessary, and is no longer generated for XAML files.

When you add support for switching language at run time, Multi-Language adds the project MLRuntime (as before) and makes a minor change to file containing the markup extension. It simple replaces the conditional compilation statement #if false with #if true, to activate the code which attaches to the language changed event handler.

(If language switching does not work, you might start by checking that this change was actually made. (:biggrin:))
---
When you use Multi-Language version 6.03 it will automatically:
*update the previous localization to use __m:Lang__ style
*remove the function __ml_UpdateControls__

The previous method is no longer supported.

Finally, this change also applies to Silverlight projects, but I have not tested it at all.%%%
If anybody is actually using Multi-Language with Silverlight and has problems, please let me know.

Phil]]></description>
      <pubDate>Sun, 07 Apr 2019 08:09:18 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1160</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1160</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Selecting the language from a ComboBox</title>
      <description><![CDATA[This information is in reply to a question on Visual Studio Marketplace.

The following is a rough description of how to add a combobox to a WinForms application to select the language at run time.

In order to switch the language at runtime, you will have to select the option "Support for Runtime Language Switching".  This command is on the runtime support menu, which is the 3rd button on Multi-Language window's toolbar.

{img src="img/wiki_up/AddRuntimeLanguageSwitching.png" }

This adds a function ml_UpdateControls() to every Form and UserControl to update the UI. 

It also adds a new Project to the solution called MLRuntime. The only purpose of this project is to broadcast an event when the language is changed. If your application contains multiple class libraries, then this will work across the component boundaries. If your application is a single project, then you can move the class MLRuntime into your project.

I added a combobox named cboLanguage to my main form.
I set the property DisplayMember to "DisplayName".

{img src="img/wiki_up/LanguageComboBox.png"}

I am going to add CultureInfo items to the combobox. I want the combobox to display the property "DisplayName" of the CultureInfo class.

In the code behind, I added a definition of the supported languages:

{CODE()}
private static string[] SupportedCultures = { "en", "de" } ; 
{CODE}
''By the way, if you use the ml_string() function, Multi-Language generates that definition in the MLString module. I might extent that in future to generate it in a different module.''

In the function InitializeComponent, I added the code

{CODE()}
foreach (String IetfTag in SupportedCultures)
{
  try
  {
    CultureInfo Cult = new CultureInfo(IetfTag);
    cboLanguage.Items.Add ( Cult ) ;

    if ( Cult.Equals ( Thread.CurrentThread.CurrentUICulture ) )
      cboLanguage.SelectedItem = Cult ;
  }
  catch{}
}

// If we didn't already select the current language, 
// then select the first language in the list.
if ( cboLanguage.SelectedItem == null )
{
  cboLanguage.SelectedItem = cboLanguage.Items[0] ;
}
{CODE}

The first part initialises the combobox items with the CultureInfo objects. If one of them is the current culture, then is makes it the selected item.

If none of the items was selected, then the second part just selects the first item in the list.

I placed this code __after__ the code inserted by Multi-Language to hook into the LanguageChanged event. That way it should immediately be able to handle language changed events.

Lastly, I added a handler for the SelectedValueChanged event, as follows:

{CODE()}
private void cboLanguage_SelectedValueChanged(object sender, EventArgs e)
{
  var SelectedCulture = cboLanguage.SelectedItem as CultureInfo ;
  Thread.CurrentThread.CurrentUICulture = SelectedCulture ;
  MLRuntime.MLRuntime.BroadcastLanguageChanged() ;
}
{CODE}

On selecting an item in the list, this:
*sets the CurrentUICulture, which is effective for any new modal forms
*broadcasts the language changed event, which is effective for the current UI, including any UserControls which have attached to this event.

I'm sure that you can make much more elegant code, but that is just one example of how it might work.]]></description>
      <pubDate>Tue, 24 Jul 2018 21:15:34 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1159</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1159</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>ASP.NET / ASPX: "Unexpected duplicate node name for HTML cache"</title>
      <description><![CDATA[Hi Phil

Looked through your log-file to find out why scanning is giving me a hard time in aspx files. I'm not sure I found my issue, but I found another one + a solution.

Please look at this code snippet:
[https://gist.github.com/anonymous/cda2ce18befd57a74f8a9ccea522e043]

The Error I'm getting is something like:
11:21:48.280858: Unexpected duplicate node name for HTML cache Test.aspx.Literal1.Text

And basically the error occurs because of the usage of "GridView" (could have been ListView or other similar controls). Basically I would recommend you reconsider your "cache naming".

As is, it would try to insert 3 items into the cache:
#Test.aspx.Literal1.Text
#Test.aspx.Literal1.Text
#Test.aspx.Literal1.Text

3 items with the same name, giving duplicate name error.

__ASPX Control ClientID__
This is actually a situation handled by ASPX already. Every control has a "ClientID" (as well as ID). "ClientID" will kind of contain the ParentID's, but not in all parent IDs. It depends if the control is having it's own scope or not - not sure how this is determined, when I look at PlaceHolder, this does __not__ have it's own scope, but GridView does.

In my example it could be 3 ID's like
#ctl00_ctl00_Literal1
#ctl00_ctl00_GridView1_ctl02_Literal1
#ctl00_ctl00_GridView1_ctl03_Literal1

__Suggestion__
If you are not able to use "ClientID" (or prefer not to), you could consider some way to find out if a ParentID defines a new scope or not, so e.g. GridView name becomes part of your name like:
#Test.aspx.Literal1.Text
#Test.aspx.GridView1.Literal1.Text
#Test.aspx.GridView2.Literal1.Text

Not sure how to do this. There might be an Attribute ([https://msdn.microsoft.com/en-us/library/system.web.ui.persistencemodeattribute(v=vs.110).aspx|PersistenceModeAttribute] ([https://msdn.microsoft.com/en-us/library/system.web.ui.persistencemode(v=vs.110).aspx|PersistenceMode enum]) on [https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.columns(v=vs.110).aspx|GridViewColumns]?) in relation to the GridView that could tell this, maybe it's the ITemplate type or similar..

This could explain some issue I've had in the past (since auto-generated ID's can cause some nasty issues).]]></description>
      <pubDate>Tue, 13 Jun 2017 11:16:39 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1139</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1139</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>ASP.NET MVC issues</title>
      <description><![CDATA[Hi Phil,

I'm having a ASP.NET MVC website and I'm facing 2 issues:

__Resource class not updated__
When I mark new strings for localization, they show up in the tool, it writes the proper code in View (most of the time), but the Resources class doesn't get the new property :'( I found out I can manually add the property to the Resources class (but it's a lot of manual work that I kind of expected the tool to do for me).

__Strings with ' causes issues__
When I scan a View with multiple strings, it will only scan until first string containing ' (like in "I'm") and skip the rest/make the rest unavailable (I found out I can remove the ' and rescan, mark new strings and add ' through the tool afterwards to overcome this - but again: I did expect the tool to do this for me) - no info in log file btw

Thanks for taking your time to read this. Let me know if you need more info.]]></description>
      <pubDate>Tue, 30 May 2017 09:03:40 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1133</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1133</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>How to translate classes that inherit Microsoft.Office.Tools.Ribbon.RibbonBase?</title>
      <description><![CDATA[Hello,
  I'm creating an Outlook addon using VSTO.
  Multi-Language Add-In doesn't translate classes that inherit Microsoft.Office.Tools.Ribbon.RibbonBase.
  RibbonBase is similar to System.Windows.Forms.Form. There is a file named .Designer.vb that contains all ribbon controls.

  Thank you for your support,
    Filippo Bottega.]]></description>
      <pubDate>Wed, 17 May 2017 12:55:11 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1129</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1129</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Rescan - Does it add to the list or purge and rebuild?</title>
      <description><![CDATA[I have previously run the Multi language tool on my project.  It build resource strings in the application and I have had translations done.  All is good.

I have now added to my application (forms, code, etc).  I would like to rescan to get the new strings built in and then have translations for the new strings.  Will I lose my existing translations if I rescan the project ?  I have
spent quite some time getting the translations and don't want to lose them.

On a related note,  If someone installs my application, and I later add translations for words I didn't have translations for at release, is there an easy way to get the translations to an existing user?  Or will I have to generate a new release and have them uninstall the old, and install the new ?

Thanks]]></description>
      <pubDate>Fri, 05 May 2017 20:21:28 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1127</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1127</guid>
      <slash:comments>0</slash:comments>
    </item>
    <item>
      <title>Translating "Culture" not supported (MVC)</title>
      <description><![CDATA[The text "Culture" cannot be translated because there is already a property called "Culture" returning the "CultureInfo".

I will suggest 2 solutions:
#Rename "CultureInfo Culture" into something unlikely to conflict (like "CultureInfo _Culture")
#Rename "string Culture" into something unlikely to conflict (like "string _Culture")]]></description>
      <pubDate>Tue, 04 Apr 2017 15:01:36 +0000</pubDate>
      <link>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1126</link>
      <guid>https://www.jollans.de/tiki/tiki-view_forum_thread.php?comments_parentId=1126</guid>
      <slash:comments>0</slash:comments>
    </item>
  </channel>
</rss>
