I have tried to raise the same concern as part of other topics, but it seems that nopCommerce team has chosen to ignore this issue for now. Since I have partially solved this dilemma myself I will try to provide hints on how this can be done. All code pointers here are in reference of version 1.9, so newer BETA will need to be revisited again to get the same functionality going.
How is language switching working now?nopCommerce maintains a cookie namely Nop.CustomerLanguage that stores a numeric language id. The same id is used for both Admin and Public site, so if you switch language in one place, it will affect language display in another.
So what's wrong with that you may ask?For starters, this just annoying when you want your Admin pages to be in english, but public site to be in user-chosen language. Since cookies are not picked up by search engines, let's review more serious ramifications:
a) When search engine indexes your site how does it know what language to index? The answer is - it doesn't, so you end up being indexed just for default language.
b) Theoretically it could have been possible to avoid this situation if only sitemaps would generate language-specific URL's both for your products, categories, manufacturers, etc., but again they don't.
c) It would be nice if HTML language settings such as "lang" attribute and meta tags would reflect the proper language culture in the content, so that browser would render it right all the time, but this goes a bit beyond a scope of this topic.
What needs to be changed to fix it?Primarily - the way language settings are preserved throughout a user session. The code that reads above mentioned cookie is sitting inside NopContext.cs file under WorkingLanguage property, this is where the magic happens. If you review the code yourself you will find setter/getter that sets the cookie as well as reads what that cookie stores on the client machine.
Language id as it's being used now has no particular value to search engines or users who view it, so it needs to be replaced by something more understandable/usable - language culture for example, so codes like "en-US", "ru-RU", etc.
This is brings us to the next step - if we decide to switch to culture codes - we need a way for the system to resolve those codes to Language (object used to retain all required information internally). Luckily this information is stored in the system and is readily available. The method to resolve the language by culture code will go into Directory/ILanguageService.cs and LanguageService.cs
/// <summary>
/// Gets a language
/// </summary>
/// <param name="cultureId">Language identifier (i.e. en-US)</param>
/// <returns>Language</returns>
public Language GetLanguageByCulture(string cultureId)
{
if (String.IsNullOrEmpty(cultureId))
return null;
string key = string.Format(LANGUAGES_BY_CULTURE, cultureId);
object obj2 = _cacheManager.Get(key);
if (this.CacheEnabled && (obj2 != null))
{
return (Language)obj2;
}
var query = from l in _context.Languages
where l.LanguageCulture == cultureId
select l;
var language = query.SingleOrDefault();
if (this.CacheEnabled)
{
_cacheManager.Add(key, language);
}
return language;
}
Merely changing the code here is not good enough since you want URL's to reflect what language it displays, so now you need to add an extra QueryString parameter to set the language and use URLRewrite to pick it up. Ideally you would want your URL to indicate your language at the top of the hierarchy (i.e. yoursite.com/en-us/products/id).