Skip to content

Instantly share code, notes, and snippets.

@johnnyreilly
Last active December 11, 2015 02:09
Show Gist options
  • Select an option

  • Save johnnyreilly/4528994 to your computer and use it in GitHub Desktop.

Select an option

Save johnnyreilly/4528994 to your computer and use it in GitHub Desktop.
Twitter.Bootstrap.MVC4 meet Bootstrap Datepicker - now with Internationalization
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Existing head content goes here -->
<!-- Added to the head to serve a meta tag like this: <meta name="accept-language" content="en-GB" /> -->
@Html.MetaAcceptLanguage()
<!-- Existing head content continues here -->
</head>
<body>
<!-- Existing body content goes here -->
<!-- Replaces the existing @Scripts.Render -->
@Scripts.Render(
"~/js",
Html.JsCultureBundle() //Serves up the "~/js-culture.de-DE" bundle for example
)
<!-- Existing body content continues here -->
</body>
</html>
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Globalization;
using System.IO;
using System.Linq;
namespace BootstrapSupport
{
public class BootstrapBundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/js").Include(
"~/Scripts/jquery-*",
"~/Scripts/globalize.js", //The Globalize library
"~/Scripts/bootstrap.js",
"~/Scripts/bootstrap-datepicker.js", //This is the brand new internationalised Bootstrap Datepicker
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.validate.unobtrusive-custom-for-bootstrap.js",
"~/Scripts/jquery.validate.globalize.js" //My jQuery Validate extension which depends on Globalize
));
//Create culture specific bundles which contain the JavaScript files that should be served for each culture
foreach (var culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
{
bundles.Add(new ScriptBundle("~/js-culture." + culture.Name).Include( //example bundle name would be "~/js-culture.en-GB"
DetermineCultureFile(culture, "~/Scripts/globalize-cultures/globalize.culture.{0}.js"), //The Globalize locale-specific JavaScript file
DetermineCultureFile(culture, "~/Scripts/bootstrap-datepicker-locales/bootstrap-datepicker.{0}.js") //The Bootstrap Datepicker locale-specific JavaScript file
));
}
bundles.Add(new StyleBundle("~/content/css").Include(
"~/Content/bootstrap.css",
"~/Content/bootstrap-datepicker.css"
));
bundles.Add(new StyleBundle("~/content/css-responsive").Include(
"~/Content/bootstrap-responsive.css"
));
}
/// <summary>
/// Given the supplied culture, determine the most appropriate Globalize culture script file that should be served up
/// </summary>
/// <param name="culture"></param>
/// <param name="filePattern">a file pattern, eg "~/Scripts/globalize-cultures/globalize.culture.{0}.js"</param>
/// <param name="defaultCulture">Default culture string to use (eg "en-GB") if one cannot be found for the supplied culture</param>
/// <returns></returns>
private static string DetermineCultureFile(CultureInfo culture,
string filePattern,
string defaultCulture = "en-GB" // I'm a Brit and this is my default
)
{
//Determine culture - GUI culture for preference, user selected culture as fallback
var regionalisedFileToUse = string.Format(filePattern, defaultCulture);
//Try to pick a more appropriate regionalisation if there is one
if (File.Exists(HttpContext.Current.Server.MapPath(string.Format(filePattern, culture.Name)))) //First try for a globalize.culture.en-GB.js style file
regionalisedFileToUse = string.Format(filePattern, culture.Name);
else if (File.Exists(HttpContext.Current.Server.MapPath(string.Format(filePattern, culture.TwoLetterISOLanguageName)))) //That failed; now try for a globalize.culture.en.js style file
regionalisedFileToUse = string.Format(filePattern, culture.TwoLetterISOLanguageName);
return regionalisedFileToUse;
}
}
}
@section Scripts {
<script type="text/javascript">
var currentCulture = $("meta[name='accept-language']").prop("content"),
language;
// Set Globalize to the current culture driven by the meta tag (if any)
if (currentCulture) {
language = (currentCulture in $.fn.datepicker.dates)
? currentCulture //a language exists which looks like "zh-CN" so we'll use it
: currentCulture.split("-")[0]; //we'll try for a language that looks like "de" and use it if it exists (otherwise it will fall back to the default)
}
//Initialise any date pickers
$('.datepicker').datepicker({ language: language });
</script>
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Linq;
using System.Web;
namespace System.Web.Mvc
{
public static class GlobalizationHelpers
{
/// <summary>
/// Taken from Scott Hanselman's blog post: http://www.hanselman.com/blog/GlobalizationInternationalizationAndLocalizationInASPNETMVC3JavaScriptAndJQueryPart1.aspx
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="htmlHelper"></param>
/// <returns></returns>
public static IHtmlString MetaAcceptLanguage<t>(this HtmlHelper<t> htmlHelper)
{
var acceptLanguage = HttpUtility.HtmlAttributeEncode(CultureInfo.CurrentUICulture.ToString());
return new HtmlString(string.Format("<meta name=\"accept-language\" content=\"{0}\" />", acceptLanguage));
}
/// <summary>
/// Return the JavaScript bundle for this users culture
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="htmlHelper"></param>
/// <returns>a culture bundle that looks something like this: "~/js-culture.en-GB"</returns>
public static string JsCultureBundle<t>(this HtmlHelper<t> htmlHelper)
{
return "~/js-culture." + CultureInfo.CurrentUICulture.ToString();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<!-- Other stuff here... -->
<globalization
culture="auto"
uiCulture="auto"
enableClientBasedCulture="true" />
</system.web>
<!-- ...and here -->
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment