Microsoft Captions Language Interface Pack

Here's another automatic translation tool from Microsoft: the Captions Language Interface Pack (CLIP). CLIP is an offline real time translator that translates whatever control is under the mouse cursor. CLIP manifests itself as a stand alone window and a tooltip (you can enable/disable both independently). Here's the window:-

Microsoft CLIP

Here's a cut out of a menu with a CLIP tooltip translating "New" into "Nouveau":-

Microsoft CLIP

At the time of writing CLIP supports translation from English (United States) to French (France) and Alsatian (France) and vice-versa but you can probably expect more languages to be added in the future.

CLIP has similarities with another Microsoft technology. Back in May 2004 Microsoft announced Microsoft Application Translator (MAT). This product was designed to translate applications on the fly. MAT was never released but I'm guessing that CLIP is using some of the same technology.

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: GuySmithFerrier
Posted on: Wednesday, August 13, 2008 at 9:00 AM
Tags:
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

ReMix UK 08: Internationalizing WPF And Silverlight Applications

ReMix UK 08 is Microsoft's 2 day UI technologies conference for designers and developers. This year it will be held in Brighton on Thursday 18th and Friday 19th September 2008 and I'm very pleased to say that I will be speaking on the Friday. My session is:-

Internationalizing WPF And Silverlight Applications
Windows Presentation Foundation (WPF) applications have as many similarities as differences from Windows Forms applications. The same is true for WPF’s localization model. This session illustrates how to localize and globalize WPF and Silverlight applications and pays particular attention to those issues that are unique to XAML, WPF and Silverlight.

There's lots to cover here and some thinking and some decisions to be made to get the right result.

See you there.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: GuySmithFerrier
Posted on: Thursday, July 31, 2008 at 11:18 PM
Tags: , ,
Categories: Events | Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

How To Write Custom FxCop Rules

I love FxCop. What I like about it most is that you can write your own FxCop rules. That means that when you define a coding rule in your development standard you can write a custom FxCop rule for it and get FxCop to enforce the rule. Certainly this speeds up code reviews but it also relieves us all from the dull drudgery of wading through code for the silly little things and allows us to spend our time using our brains instead.

I've been writing custom FxCop rules for a number of years and although I'm a big fan the part where I get to writing the rules has traditionally been a lot of pain. The reason is that there wasn't any documentation for the SDK - you had to work it out yourself. I wrote Chapter 13 of .NET Internationalization explaining how to write custom rules but this was focused more on what it meant to the world of internationalization than all of the details of how to write rules. Well now the pain can go away for everyone. Everyone put their hands together for Jason Kresowaty. Jason took it upon himself to write the documentation for the FxCop SDK! Microsoft didn't ask him to do it, he just did it anyway. And it's very good (you can download it here). What's even better is he wrote Introspector (available for download at the same location). Introspector does for introspection of assemblies what Reflector does for reflection of assemblies. FxCop is based on Microsoft's introspection engine (FxCop hasn't used reflection for some years now) so an Introspection tool is a godsend (or a Jason-send in this case).

Thanks, Jason, this is a big deal.

(Alternatively, if you don't want to read the docs I gave a presentation on this at a VBUG Conference and you can download a video of this presentation here and the slides here).

 

Technorati Tags: FxCop, Jason Kresowaty, Introspector, Introspection

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: GuySmithFerrier
Posted on: Thursday, July 10, 2008 at 9:50 PM
Tags:
Categories: Internationalization | Miscellaneous - Technical
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Public Strongly Typed Resources With PublicResXFileCodeGenerator

One of the new localization features in Visual Studio 2008 is the PublicResXFileCodeGenerator. In both Visual Studio 2005 and 2008 you can create a resource file (e.g. ExceptionResources.resx) and Visual Studio will associate a .Designer.cs file (e.g. ExceptionResources.Designer.cs) with it. The .Designer.cs file contains a strongly typed resource class that allows you to refer to the resource entries as properties of the generated class (e.g. ExceptionResources.CustomExceptionMessage). This system works well but the class and its properties are marked as internal and consequently they can only be accessed from within the same assembly. Visual Studio 2008 allows these classes and their properties to be public. By default the resources are still internal and you can see this by selecting the .resx file in Solution Explorer and then bringing up the Properties Window. You will see a property called Custom Tool and it will be set to ResXFileCodeGenerator. This is the code generator that uses the .NET Framework's StronglyTypedResourceBuilder class to generate the code for the .Designer.cs file. The StronglyTypedResourceBuilder (and its associated command line tool ResGen) both accept a parameter to generate public resources but the ResXFileCodeGenerator sets this value to false and so the resources are internal. Visual Studio 2008, however, introduces a new generator called a PublicResXFileCodeGenerator and this generator sets this value to true. To generate public strongly typed resource classes instead of internal ones set the Custom Tool to PublicResXFileCodeGenerator.

Alternatively you can set the Access Modifier drop down in the Resource Editor to Public to achieve the same result (there are three values: Internal, Public and No code generation). It is worth knowing that this Visual Studio 2008 feature is simply a design time feature and the generated code is still .NET Framework 2.0 compatible.

Of course, it is also possible to write your own replacement for the ResXFileCodeGenerator and PublicResXFileCodeGenerator and you can download an example of this at http://www.dotneti18n.com/downloads.aspx.

Technorati Tags: Localization, Internationalization, ResXFileCodeGenerator, PublicResXFileCodeGenerator, Strongly Typed Resource Classes, resx

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Visual Studio 2008 And Generate Local Resources

Some of the changes in Visual Studio 2008 are a bit subtle. One of them is the way the Generate Local Resources option works (Tools | Generate Local Resources is used to make a web form localizable). In both Visual Studio 2005 and 2008 Generate Local Resources adds culture="auto" and uiculture="auto" to the page’s directives. These settings make the page responsive to the browser’s language setting (in IE7 select Tools | Internet Options and click on the Languages button). This is very convenient for testing and can also be acceptable for development purposes depending on how you expect to learn your user’s language preference. However, it is slightly flawed in Visual Studio 2005. The problem is that if you set the culture and uiculture in the website’s web.config (in order to force the entire website to use a single culture) the values are overridden at the page level rendering the web.config’s values meaningless. The solution would appear to be obvious and that is to delete the culture="auto" and uiculture="auto" attributes from the page directives. This solution works fine but unfortunately Visual Studio 2005 doesn’t respect your change and the next time you run Generate Local Resources the values are restored.

In Visual Studio 2005 the simplest solution to this problem is to remember to delete the culture and uiculture attributes from the page immediately after you run Generate Local Resources. An alternative but potentially debateable solution is to set the culture and uiculture values to a valid culture that you will never use - effectively a dummy culture. Then you override the page’s InitializeCulture method and check the culture and uiculture values to see if they are the dummy culture and if they are you set the culture back to your chosen culture.

Visual Studio 2008, however, solves this problem simply by only adding the culture and uiculture attributes the first time it is run on a page and so if you delete them then they stay deleted. This is a small change to Visual Studio but it has a big impact if this is your model. Remember this is a change to the Visual Studio 2008 IDE and so you can benefit from this in your .NET Framework 2.0 applications if you maintain them using Visual Studio 2008 (because it is multi-targetting).

Technorati Tags: Visual Studio 2008, Visual Studio 2005, Generate Local Resources, Localization, Internationalization

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Guy Smith-Ferrier
Posted on: Monday, March 31, 2008 at 8:59 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

MSDN Article: Internationalizing ASP.NET AJAX

My first MSDN Magazine article entitled "Around the World with ASP.NET AJAX Applications" has been published in the January 2008 issue. The article is all about how to localize and globalize ASP.NET AJAX applications. The article also explains how the assembly-based localization model works and you can download the Script Resource Viewer utility that I wrote to diagnose this behavior here. You can also download the slides that accompany the presentation I have given on Internationalizing ASP.NET AJAX here.

Technorati Tags: Internationalizing ASP.NET AJAX, Internationalization, Localization, Globalization, ASP.NET, ASP.NET AJAX, MSDN Magazine

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Guy Smith-Ferrier
Posted on: Thursday, December 20, 2007 at 9:15 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (4) | Post RSSRSS comment feed

Setting The ClickOnce PublishState In Internationalized Applications

There is quite a bit to know about deploying internationalized applications using ClickOnce. I cover this subject in the Windows Forms Specifics chapter of my book .NET Internationalization and also in my presentation "Deploying Internationalized Applications Using ClickOnce" (slides, MSDN Webcast). One of the problems that arises in this process is how to set the PublishState of localized files that are deployed using ClickOnce. This post explains the utilities that I have written for this purpose. You can download the source code the book (including these utilities) from http://www.dotneti18n.com/downloads.aspx.

Here’s a very quick introduction to the issue that this post is concerned with (the whole subject is much bigger than just what I’m covering here). Say you have a Windows Forms application that has been localized into many different cultures (e.g. French, French (France), French (Canada), Spanish, Spanish (Spain) and Spanish (Mexico)). Now open up the project’s Properties, select the Publish tab, click on the "Application Files..." button and check the "Show all files" checkbox. You will see all of the localized resource files (e.g. fr\WindowsApplication1.resources.dll, fr-FR\WindowsApplication1.resources.dll etc.). By default the Publish Status will be set to "Auto". This means that whether the file is included or not is determined by the Publish Language. In some scenarios (e.g. publishing families of related cultures) you want to take explicit control over this process and manually include or exclude these files regardless of the setting of the Publish Language. This is easy to do with Visual Studio - you just drop down the combo box and set it to Include or Exclude. It is much harder to do with msbuild (where it is arguably more important because you want to automate the build process) and that’s what the utilities in this post are for.

In Visual Studio if you set the French resources to Include you will see the following section added to the .csproj or .vbproj file in one of the ItemsGroup elements:-

PublishFile Include="fr\WindowsApplication1.resources"

This PublishFile will have a PublishState that is set to "Include". There is no way to set this value using msbuild. Until now. Introducing the SetPublishState command line utility and the SetPublishStateTask msbuild task (these are included in the downloadable Visual Studio 2005 source code for the .NET Internationalization book that you can download here).

The SetPublishState command line utility can be called like this:-

SetPublishState WindowsApplication1.csproj fr:Include fr-FR:Include fr-CA:Include All:Exclude

The first parameter is the name of the project file to change. The remaining parameters are a list of cultures and whether to set them to Include or Exclude. Notice the "All" parameter at the end of the list. This optional parameter specifies what to set all of the remaining other cultures to. So in this example the fr, fr-FR and fr-CA cultures are set to Include and the es, es-ES and es-MX cultures are set to Exclude. This would be correct if you wanted to publish the French cultures in one operation. Having performed the publish operation you would then execute the following command:-

SetPublishState WindowsAppl

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Guy Smith-Ferrier
Posted on: Sunday, November 04, 2007 at 6:49 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Preserving Windows Forms resx Comments

One of the problems with auto-generated files is that if you make changes to them then your changes are lost the next time the file is re-generated. This happens with resx files for localized Windows Forms. If you set Form.Localizable to true and then edit the resx file directly then the next time Visual Studio rebuilds the resx file your changes are lost. One reason why you might want to edit the resx file is to add comments to the entries but obviously these comments will be lost. In fairness to Visual Studio a clear and strong warning is given when you attempt to edit a form’s resx file directly so it is difficult to make this mistake accidentally. However, the question remains "what if you wanted to preserve your comments between rebuilds of the resx file ?" This is achievable using the CopyComments method shown below. This method accepts an input resx and an output resx and copies the comments from the input resx to corresponding entries in the output resx. The idea is that prior to allowing Visual Studio to rebuild the resx file you take a copy of it. After Visual Studio has rebuilt the resx file (and the comments have been lost) you run this utility to copy the comments back into the ’main’ resx file.

public static Boolean CopyComments(string inputResX, string outputResX)
{
bool changesMade = false;

// populate a Hashtable containing the DataNodes in the output file
Hashtable output = new Hashtable();
using (ResXResourceReader reader = new ResXResourceReader(outputResX))
{
reader.UseResXDataNodes = true;
IEnumerator enumerator = reader.GetEnumerator();
while (enumerator.MoveNext())
{
DictionaryEntry entry = (DictionaryEntry)enumerator.Current;

ResXDataNode dataNode = (ResXDataNode)entry.Value;
output.Add(dataNode.Name, dataNode);
}
}

// search the Hashtable for equivalent DataNodes in the input file
using (ResXResourceReader reader = new ResXResourceReader(inputResX))
{
reader.UseResXDataNodes = true;
IEnumerator enumerator = reader.GetEnumerator();
while (enumerator.MoveNext())
{
DictionaryEntry entry = (DictionaryEntry)enumerator.Current;

ResXDataNode inputDataNode = (ResXDataNode)entry.Value;

if (output.ContainsKey(inputDataNode.Name))
{
ResXDataNode outputDataNode = (ResXDataNode)output[inputDataNode.Name];
if (!String.IsNullOrEmpty(inputDataNode.Comment) &&
outputDataNode.Comment != inputDataNode.Comment)
{
// update the output resx’s comments with the input resx’s comments
outputDataNode.Comment = inputDataNode.Comment;
changesMade = true;
}
}
}
}
if (changesMade)
{
// write the changes back to the output file
using (ResXResourceWriter writer = new ResXResourceWriter(outputResX))
{
foreach (DictionaryEntry entry in output)
{
writer.AddResource(entry.Key.ToString(), entry.Value);
}
writer.Generate();
writer.Close();
}
}

return changesMade;
}
}

Technorati Tags: Internationalization, Windows Forms,

Posted by: Guy Smith-Ferrier
Posted on: Monday, August 06, 2007 at 9:05 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Displaying Currencies In Your Local Format

Here’s a globalization problem that was put to me recently: how to display a foreign currency in your local format ?

For example if I have a value 123,456.78 and my application is using the en-GB (English (United Kingdom)) culture then this value will display as "£123,456.78". This is correct if the value itself refers to UK Pounds but it is completely incorrect if it refers to US Dollars. If the value refers to US Dollars you could simply display the value using the "English (United States)" culture:-

123456.78.ToString("C", new CultureInfo("en-US"))

This displays "$123,456.78". The double.ToString method accepts an IFormatProvider parameter and extracts the NumberFormatInfo from the CultureInfo object that we pass.

This works in this example but only because the number and currency formatting rules for en-US are the same as for en-GB. If you use a culture with different formatting rules to that of your users then the resulting string will be confusing. For example the correct display of the same value using Hungarian Forints in Hungary is "123 546,78 Ft" but this will give rise to confusion for a reader who uses English (United Kingdom) or English (United States) formatting. What is needed is a way of displaying a foreign currency in a format that the local user will understand.

One solution is the simple DisplayCurrency class below. The static GetNumberFormatInfo method returns a NumberFormatInfo object that is a combination of the currency’s NumberFormatInfo object and the CurrentCulture’s NumberFormatInfo object.

public class DisplayCurrency
{
public static NumberFormatInfo GetNumberFormatInfo(CultureInfo currencyCultureInfo)
{
return GetNumberFormatInfo(currencyCultureInfo, CultureInfo.CurrentCulture);
}
public static NumberFormatInfo GetNumberFormatInfo(CultureInfo currencyCultureInfo, CultureInfo displayCultureInfo)
{
NumberFormatInfo combinedNfi = (NumberFormatInfo)displayCultureInfo.NumberFormat.Clone();
NumberFormatInfo currencyNfi = currencyCultureInfo.NumberFormat;
if (currencyNfi.NumberDecimalDigits > combinedNfi.NumberDecimalDigits)
// increase the decimals to accomodate the target’s decimals
combinedNfi.NumberDecimalDigits = currencyNfi.NumberDecimalDigits;

combinedNfi.CurrencySymbol = currencyNfi.CurrencySymbol;
return combinedNfi;
}
}

The combination is minimalistic in that the new NumberFormatInfo object merely borrows the CurrencySymbol from the currency’s NumberFormatInfo object. In addition it checks the currency’s NumberDecimalDigits and increases the new NumberDecimalDigits if it is lower. This is to ensure that a currency that normally contains decimals does not have its decimals incorrectly truncated. So for example displaying "€123,456.78" when the user’s culture is "ja-JP" (Japanese (Japan)) should not truncate to "€123,456" simply because the Japanese Yen does not have decimals.

Here are the results for a few example cultures:-

hu-HU,Hungarian (Hungary), Hungarian Forint, -123 456,78 Ft, -Ft123,456.78
it-CH,Italian (Switzerland), Swiss Franc, SFr.-123’456.78, -SFr.123,456.78
ms-BN,Malay (Brunei Darussalam), Brunei Dollar, ($123.457), -$123,456.78
fr-CA,French (Canada), Canadian Dollar, (123 456,78 $), -$123,456.78

The solution is not without its problems, however. Like many globalization solutions it makes assumptions about the consumer of the information. In this case it assumes that the user is unfamiliar with the original currency. In the case of the Estonian Kroon, the Malaysian Ringgit and the Guatemalan Quetzal this may well be true. In these examples the solution helpfully displays the currency using formatting that the user is familiar with.<

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Guy Smith-Ferrier
Posted on: Sunday, July 29, 2007 at 4:45 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

VBUG Bournemouth: Internationalizing ASP.NET AJAX (Slides)

Many thanks to everyone in Bournemouth who turned up to the VBUG meeting at the university last night. As promised you can download the slides here.

You can also download the slides that I used for the internationalization recap here.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: Guy Smith-Ferrier
Posted on: Friday, May 25, 2007 at 8:56 PM
Categories: Internationalization
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (2) | Post RSSRSS comment feed