Ajout de la prise en charge de la langue seconde avec le chemin racine dans un site Web ASP.NET existant

J’ai hérité d’un très petit projet WebForms ASP.NET et mon client souhaite y append une deuxième langue.

Pour chaque “somepage.aspx”, j’aimerais utiliser une version de “deuxième langue”, comme “fr / somepage.aspx”. J’aimerais gérer cela en utilisant la globalisation normale (CurrentCulture + fichiers de ressources dans les deux langues) et éviter de dupliquer chaque page. Je dois garder les chemins d’origine valides, c’est pourquoi j’ai exclu ASP.NET MVC pour l’instant (faute de savoir si je pourrais continuer à prendre en charge les chemins “.aspx”).

Est-ce possible?

Le routage d’URL est disponible dans ASP.NET.

Vous pouvez créer deux itinéraires, le premier étant l’itinéraire qui intercepte votre langue:

{langue} / {page}

Le deuxième itinéraire serait juste

{page}

Dans MVC, nous pouvons créer des contraintes de route qui imposeraient au langage d’avoir une valeur spécifique (comme en, en-us, etc.). Je ne suis pas certain si la même chose peut être faite dans le routage ASP.NET WebForms normal.

Voici deux articles décrivant le sujet du routage dans WebForms (non-MVC)

http://msdn.microsoft.com/en-us/magazine/dd347546.aspx

et

http://weblogs.asp.net/scottgu/archive/2009/10/13/url-routing-with-asp-net-4-web-forms-vs-2010-and-net-4-0-series. aspx

MODIFIÉ POUR AJOUTER UN ÉCHANTILLON DE CODE

Dans mon Global.asax, j’ai enregistré ce qui suit:

void RegisterRoutes(RouteCollection routes) { routes.Ignore("{resource}.asxd/{*pathInfo}"); routes.Add( new Route( "{locale}/{*url}", //Route Path null, //Default Route Values new RouteValueDictionary{{"locale", "[az]{2}"}}, //constraint to say the locale must be 2 letters. You could also use something like "en-us|en-gn|ru" to specify a full list of languages new Utility.Handlers.DefaultRouteHandeler() //Instance of a class to handle the routing )); } void Application_Start(object sender, EventArgs e) { // Code that runs on application startup RegisterRoutes(RouteTable.Routes); } 

J’ai également créé une classe séparée (voir routage des formulaires Web asp.net 4.0 – route par défaut / générique, à titre indicatif).

 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Compilation; using System.Web.Routing; using System.Web.UI; namespace SampleWeb.Utility.Handlers { public class DefaultRouteHandeler:IRouteHandler { public IHttpHandler GetHttpHandler(RequestContext requestContext) { //Url mapping however you want here: ssortingng routeURL = requestContext.RouteData.Values["url"] as ssortingng ; ssortingng pageUrl = "~/" + (!Ssortingng.IsNullOrEmpty(routeURL)? routeURL:""); var page = BuildManager.CreateInstanceFromVirtualPath(pageUrl, typeof(Page)) as IHttpHandler; if (page != null) { //Set the 
's postback url to the route var webForm = page as Page; if (webForm != null) webForm.Load += delegate { webForm.Form.Action = requestContext.HttpContext.Request.RawUrl; }; } return page; } } }

Cela fonctionne car, lorsqu’aucune langue n’est spécifiée dans l’URL, le moteur de vue par défaut pour Web Forms prend le relais. Cela fonctionne aussi quand une locale de 2 lettres (en? Us? Etc) est utilisée. Dans MVC, nous pouvons utiliser une commande IRouteConstraint et effectuer toutes sortes de vérifications, comme s’assurer que les parameters régionaux sont dans une liste, vérifier si le chemin existe, etc.

Maintenant, je sais qu’il ya un problème avec le code tel quel, les documents par défaut ne se chargent pas. Ainsi, http: // localhost: 25436 / en / ne charge pas le document par défaut de default.aspx, mais http: // localhost: 25436 / en / default.aspx fonctionne. Je vous laisse le soin de le résoudre.

J’ai testé cela avec des sous-répertoires et cela fonctionne.

Vous pouvez créer un module HTTP ASP.NET qui appelle HttpContext.RewritePath pour mapper les demandes de “fr / somepage.aspx” à “somepage.aspx”. Cette technique fonctionne mieux avec IIS 7.0 en mode intégré car les URL relatives aux scripts et aux feuilles de style sont résolues en chemins tels que “/fr/jquery.js” et doivent également être mappés à “/jquery.js”.

 namespace SampleApp { public class LocalizationModule : IHttpModule { private HashSet _supportedCultures = new HashSet(SsortingngComparer.OrdinalIgnoreCase) { "de", "es", "fr" }; private ssortingng _appPath = HttpRuntime.AppDomainAppVirtualPath; public void Dispose() { } public void Init(HttpApplication application) { application.BeginRequest += this.BeginRequest; _appPath = HttpRuntime.AppDomainAppVirtualPath; if (!_appPath.EndsWith("/")) _appPath += "/"; } private void BeginRequest(object sender, EventArgs e) { HttpContext context = ((HttpApplication)sender).Context; ssortingng path = context.Request.Path; ssortingng cultureName = this.GetCultureFromPath(ref path); if (cultureName != null) { Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName); context.RewritePath(path); } } private ssortingng GetCultureFromPath(ref ssortingng path) { if (path.StartsWith(_appPath, SsortingngComparison.OrdinalIgnoreCase)) { int startIndex = _appPath.Length; int index = path.IndexOf('/', startIndex); if (index > startIndex) { ssortingng cultureName = path.Subssortingng(startIndex, index - startIndex); if (_supportedCultures.Contains(cultureName)) { path = _appPath + path.Subssortingng(index + 1); return cultureName; } } } return null; } } } 

Web.config:

             

Vous pouvez mettre à jour Application_BeginRequest dans Global.Asax avec ces codes. Si global.asax n’existe pas, créez-le.

Le chemin virtuel du projet Visual Studio doit être /

 protected void Application_BeginRequest(object sender, EventArgs e) { ssortingng file_path = Request.RawUrl.ToLower(); char[] separator = new char[] { '/' }; ssortingng[] parts = file_path.Split(separator, SsortingngSplitOptions.RemoveEmptyEnsortinges); if (parts.Length > 0 && parts[0] == "fr") { System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR"); Context.RewritePath("~/" + file_path.Subssortingng(4), true); } else { System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); } } 

Une option consiste à placer les textes de l’aspx dans les balises <%$ Resources: My translated text %> . Les balises de ressources seront résolues à l’aide d’un ResourceProviderFactory pour obtenir la valeur traduite. Ce ResourceProviderFactory que vous pouvez créer vous-même, en effectuant le travail d’extraction de la traduction à partir d’un fichier de ressources ou d’une firebase database, par exemple (Il suffit de mettre en œuvre IResourceProvider.GetObject() ). Vous configurez ceci dans le web.config:

    

Voir: http://msdn.microsoft.com/en-us/library/fw69ke6f(v=vs.80).aspx