Summary: In this short article I will describe the creation of a Visual Studio.NET 2005 macro that speeds up the process of adding localizable controls to ASP.NET web pages, briefly touching on the subjects of ASP.NET localization, regular expressions and world peace.
Not really world peace.
I will assume you are familiar with writing ASP.NET pages and working with regular expressions.
Intro on ASP.NET Globalization
Globalization is the process of building an application in a way that it's GUI can appear in diferrent languages and cultural formats. ASP.NET 2.0 has some mechanisms that simplify building globalized apps with (relatively) little hassle.
One of the widest used mechanisms is called implicit localization expressions. It works by placing a special attribute, meta:resourcekey on an ASP.NET control in the page:
<asp:label id="Header" runat="server" meta:resourcekey="Header"></asp:label>
Now, you can create resource files in the App_LocalResources directory of the web project. The resource files must adhere to the naming convention:
[LocalizedWebFormName].resx
So if the above asp:label is in a file named Default.aspx, the resource file will be named Default.aspx.resx.
In the resource file you can now add resources with names that match the values in the meta:resourcekey attributes of the localized controls and the property names of the controls that you want to localize(such as the Text property of an asp:label control).
For example:

When you run the page, ASP.NET will automatically populate the properties of the localized control with the values from the resource file.
Now for the localization part - you can supply resource files for every language and culture you wish to support by creating a resource file named in the following convention:
[LocalizedWebFormName].[Language Code].resx
For example:
Default.aspx.en.resx
Default.aspx.fr.resx
Default.aspx.he.resx
The beauty is that ASP.NET will load properties with values from the resource file that matches the culture of the current thread, based on the current culture of the requesting user's machine. So when a user from Israel will request the page she will get the Hebrew values automatically.
Very Cool, But There's a Rub
Now you can build globalized web pages by dragging controls, adding the meta:resourcekey attribute and adding the needed property resources to the resource file.
One problem is that creating even simple pages that contain many controls can become tedious, because now you have to spend much more time on every control you drag to the web page.
How can we automate the process of adding the extra attributes and resources?
VS Macros 101
Visual Studio.NET 2005 contains two main customization and extension mechanisms: Macros and Add-Ins. Generally speaking Macros are less powerful but easier to create. Add-Ins are more powerful and are a bit more complicated to create.
VS Macros are actually Visual Basic for Applications code (that's right, no VB.NET and definitely no C#) intended primary for automating repetitive tasks in Visual Studio.
The easiest way to create a macro is by using the Record Macro command:

Recording a macro in this way actually creates VBA code behind the scenes. You then can edit that code and also create new macros programmatically using the Macros IDE. This code can access many parts of the Visual Studio environment such as the files ad the code inside them, via different classes in the EnvDTE namespace.
Good places to start learning about how you can access the various parts of VS are:
1. Automation and Extensibility reference on MSDN.
2. Opening the Macros IDE and reading the code in the Samples project.
3. Recording macros and going through the code that VS creates automatically.
Back to the Problem, Macro For Localized Controls
Lets draw an outline for one possible solution:
The user will create the controls normally, then select in the editor all the controls that need to be localized and run the macro. The macro will go through the controls that are found within the selection, creating a meta:resourcekey attribute for each one (the attribute value will be the same as the value of the id attribute) and also creating a resource for each control in the appropriate resource file.
Writing the Macro - Adding Localization Attributes to the Web Page
We'll start out by adding a new public method to the macros module:
Sub LocalizeControls()
End Sub
The procedure is public by default. Private procedures will not be accessible from the IDE and cannot be used as macro entry-points.
We will use regular expressions to find all the ASP.NET controls inside the selection and to append the meta:resourcekey attributes. The following code section does just that:
Const ControlsMatchingPattern = "(?<tag><asp[^>]*id=" & Chr(34) & "(?<id>[^" & Chr(34) & "]*)" & Chr(34) & "[^>]*text=" & Chr(34) & "(?<text>[^" & Chr(34) & "]*)" & Chr(34) & "[^>]*)>"
Function AddMetaResourceKeyToControls(ByVal ControlsHtml As String)
Dim ControlsRegexExpression As New Regex(ControlsMatchingPattern, Re