Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
I

i18n

> 编程语言
Open source

Smart internationalization for ASP.NET

560 stars0 likes0 views
WebsiteGitHub

About

Smart internationalization for ASP.NET

i18n (v2)

Smart internationalization for ASP.NET

    PM> Install-Package i18N

Introduction

The i18n library is designed to replace the use of .NET resources in favor of an easier, globally recognized standard for localizing ASP.NET-based web applications.

Platforms Supported

i18n itself targets .NET Framework 4, and works with websites and web applications based on ASP.NET v4 and above, including:

  • ASP.NET MVC
  • ASP.NET Web API
  • ASP.NET WebMatrix / Web Pages
  • ASP.NET Web Forms

Features

  • Leverages the GetText / PO ecosystem: localize like the big kids
  • Localize everything: HTML, Razor, C#, VB, JavaScript, .NET attributes and data annotations, ...
  • SEO-friendly: language selection varies the URL, and Content-Language is set appropriately
  • Automatic: no URL/routing changes required in the app
  • High performance, minimal overhead and minimal heap allocations
  • Unit testing support
  • Smart: knows when to hold them, fold them, walk away, or run, based on i18n best practices

Project Configuration

The i18n library works by modifying your HTTP traffic to perform string replacement and patching of URLs with language tags (URL Localization). The work is done by an HttpModule called i18n.LocalizingModule which should be enabled in your web.config file as follows:

  
    
      
    
  
   
    
      
    
  

Note: The `````` element is added for completeness and may not be required.

The following `````` are then required to specify the type and location of your application's source files:

  
     
    
    
  

The following configuration options are optional. i18n.DisableReferences allows you to generate lighter pot/po files by deleting references to your translation tokens (nuggets) and i18n.GenerateTemplatePerFile generates a pot file per file scanned and merges all po files into messages.po:

  
    
    
  

Certain behaviours of i18n may be altered at runtime on application startup. The following code shows the most common options:

…

Usage

To localize text in your application, surround your strings with [[[ and ]]] markup characters to mark them as translatable. That's it. Here's an example of localizing text in a Razor view:

    

And here's an example in an MVC controller:

    using i18n;
    
    namespace MyApplication
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                ViewBag.Message = "[[[Welcome to ASP.NET MVC!]]]";

                return View();
            }
        }
    }

At last, you can localize your data annotations as easy as this:

    public class PasswordResetViewModel
    {
        [Required(ErrorMessage="[[[Please fill in this field]]]")]
        [Email(ErrorMessage = "[[[Email not yet correct]]]")]
        [Display(Name = "[[[Email Address]]]")]
        public string Email
        {
            get;
            set;
        }
    }

And localize arguments passed to MVC URL-Helpers or other functions that require a plain string:

@Html.LabelFor(m => m.Name, "[[[First Name]]]")

And for Javascript:

    

Nuggets

In PO terminology, strings you want to be translatable are known as messages. In i18n, messages are 'marked-up' in your source code as 'Nuggets'. The nugget markup allows i18n to filter the HTTP response looking for the message strings which are replaced with translated strings, where available. They also allow message strings to be located by the PostBuild PO file generator.

A simple nugget looks like this:

[[[translate me]]]

This defines a message with the key (aka msgid) of "translate me".

Nugget markup supports formated messages as follows:

string.Format("[[[welcome %1, today is %0|||{0}|||{1}]]]", day, name)

where the %0 and %1 tokens are replaced by the strings that replace the {0} and {1} items, respectively. (The reason for the extra level of redirection here is to facilitate the translator rearranging the order of the tokens for different languages.)

Nugget transformation supports translation of the arguments as follows:

[DisplayName("[[[CountryCode]]]")]
[MaxLength(20, ErrorMessage="[[[%0 must be %1 characters or less|||(((CountryCode)))|||20]]]")]
public string CountryCode { get; set; }

where the Nugget markup will first replace (((CountryCode)) with the translated text and then merge the translated value into the main message.

Nugget markup supports comments (extracted comments in PO terminology) to be passed to the translator like so:

[[[translate me///this is an extracted comment]]]

And if you need to include the markup characters themselves within a message, you can HTML-escape them, for example:

[[[Please don't forget to add GoogleAd tags: [googleadsmall&#93;]]]

where &#93; is the HTML escape sequence for ]. The relevant escape sequences are:

  • / = &#47;
  • [ = &#91;
  • ] = &#93;
  • | = &#124;

See Issue #50 for more on Nuggets and why we have chosen to replace the GetText / _() style of marking-up messages.

Nugget markup customization

The character sequences for marking-up nuggets ([[[, ]]], |||, (((, ))) and ///) were chosen on the basis that they were unlikely to clash with common character sequences in HTML markup while at the same time being convenient for the programmer to enter (on most keyboards).

However, recognizing that a clash remains possible and nuggets thereby being falsely detected in source code or the HTML response, i18n allows you to define your own sequences for the markup which you know are not going to clash. You can configure these in web.config as follows:

  
    ...
    
    
    
    
    
    
    ...
  

Message Visualization

i18n can be configured to visualize all processed messages. This is useful when testing your app to verify that all messages are tagged correctly. To enable this feature:

  
    ...
    
    
    ...
  

When VisualizeMessages is active the NuggetVisualizeToken will be inserted at start and end of each translated message.

Two more optional parameters can be used to further customize the message visualization. i18n.VisualizeLanguageSeparator This enables display of the language tag that was use to localize each message. The language tag will be shown before each message, separated from the message by this parameter value. If the value is a blank string or the parameter is not present then language tags are not shown in message visualizations. i18n.NuggetVisualizeEndToken This allows for using different start and end tokens for visualizing messages. When this value is specified then the NuggetVisualizeToken will be inserted at start of each translated message and the NuggetVisualizeEndToken will be inserted at end of each translated message.

For example, to display language tags separated from messages by a colon, and add brackets to enclose the visualized messages, use the following message visualization configuration.

  
    ...
    
    
    
    
    ...
  

Message Context Support

i18n allows you to assign a msgctxt value to each message. The value of the msgctxt is taken from any comment you have defined in the nugget. This feature is optional and disabled by default. To enable this feature:

  
    ...
    
    ...
  

Note that note all PO editors support msgctxt and indeed may be thrown by the value when present in .PO files. See Issue #90 for more details.

Multi-line messages

The PO spec supports messages that span multiple lines. i18n provides full support for these, simply by spreading the nugget over several lines.

For example, the following nugget is perfectly legal and should appear in your PO editor as a multi-line message:

[[[This is a
message spread over
three lines]]]

Static File Compression and i18n

The i18n module localizes nuggets in the HTTP response by modifying the response stream using a response filter (see the .NET Framework documentation for more info about the HttpResponse.Filter property). If the response stream is compressed before it reaches the i18n module then the module does not modify the stream. Currently the module is not designed to intercept static file requests before compression happens.

Two checks are implemented to ensure that the module does not modify compressed response streams:

  1. In i18n.LocalizingModule there is a check to see if the response Content-Encoding header is set to "gzip" and if it is then the module does not install the response filter.
  2. In i18n.ResponseFilter the stream content is checked for the presence of the gzip file format magic number (the first two bytes of a gzip file are set to 1F 8B). If the magic number is found at the beginning of the stream then the content is passed through without modification by the filter.

Because of the way that static file compression works in IIS, some responses to static files requests do not get compressed, so if you have static file compression enabled (it is enabled by default) AND you have nuggets within the content of a static file, then the response received by a client will be localized when the response is not compressed and it will not be localized when the response is compressed. In order to prevent this, it is important that you decide whether or not you will localize static files on your site because you need to do one of the following:

  1. If you want to use nuggets and localize static files - disable static file compression. This means that you will not get the benefit of the bandwidth savings of compressing static files, but if you are localizing static files then you have essentially taken the decision to make the static files dynamic.
  2. If you do not need to use nuggets and localize static files - leave static file compression enabled. You will now get the benefit of the bandwidth savings of compressing static files, but it is important that you must not put nuggets in the static files.

Note: Refer to Issue #163 for more on IIS compression settings.

Note: in some scenarios, it might be desirable to localize Javascipt (.js) files, making your application case 1. To easily disable static file compression, use the IIS manager and click on site name, Compression and uncheck "Enable static content compression".

Note: The Microsoft ScriptManager compresses responses to requests for ScriptResource.axd so these responses will always be compressed and the script that is returned by the ScriptManager will not be localized even if you disable static file compression.

Building PO databases

To set up automatic PO database building, add the following post-build task to your project, after adding i18n.PostBuild.exe as a project reference:

    "$(TargetDir)i18n.PostBuild.exe" "$(ProjectDir)\web.config"

You can find i18n.PostBuild.exe file under packages folder:

    {your_solution}\packages\{package_version}\tools\i18n.PostBuild\i18n.PostBuild.exe

Alternatively, you may choose to install the i18n.POTGenerator.vsix Visual Studio extension (2012/2013). This installs an i18n button in the Solution Window for manual triggering of PO generation. Note that it is necessary to highlight the project in question within the Solution Window before pressing the button.

The PO generator will rip through your source code (as defined by the i18n.DirectoriesToScan and i18n.WhiteList settings in web.config), finding every nugget, and uses this to build a master .POT template file located at locale/messages.pot relative to your web application folder. Afte

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C#

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言