using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Xml.Linq;
using System.Web.UI.HtmlControls;
public partial class ResourceManage: System.Web.UI.Page
{
private string[] otherCultures = new[] { "nl-NL" };
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindResources();
}
lbMessage.Text = string.Empty;
}
private void BindResources()
{
TreeNode localResourceNode = new TreeNode("App_LocalResources");
localResourceNode.Expanded = true;
tv.Nodes.Add(localResourceNode);
string rootPath = Server.MapPath("~/");
DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);
BuildLocalResouceNode(localResourceNode, rootDirectory);
divButton.Visible = false;
lvResource.DataSource = null;
lvResource.DataBind();
}
private bool BuildLocalResouceNode(TreeNode node, DirectoryInfo directory)
{
if (directory.GetFiles("*.as?x.resx", SearchOption.AllDirectories).Length < 1 &&
directory.GetFiles("*.master.resx", SearchOption.AllDirectories).Length < 1)
return false;
DirectoryInfo[] subDirectories = directory.GetDirectories();
var resourceDirectories = subDirectories.Where(d => d.Name.ToLower() == "app_localresources");
var nonResourceDirectories = subDirectories.Except(resourceDirectories);
foreach (DirectoryInfo nd in nonResourceDirectories)
{
TreeNode nSubNode = new TreeNode(nd.Name);
if (BuildLocalResouceNode(nSubNode, nd))
{
node.ChildNodes.Add(nSubNode);
}
else
{
//nSubNode.Dispose();
}
}
foreach (DirectoryInfo rd in resourceDirectories)
{
var resourceFiles = rd.GetFiles("*.as?x.resx", SearchOption.TopDirectoryOnly).OrderBy(f => f.Name)
.Select(f => new { Name = Path.GetFileNameWithoutExtension(f.Name), FullName = f.FullName });
var masterFiles = rd.GetFiles("*.master.resx", SearchOption.TopDirectoryOnly).OrderBy(f => f.Name)
.Select(f => new { Name = Path.GetFileNameWithoutExtension(f.Name), FullName = f.FullName });
resourceFiles = resourceFiles.Union(masterFiles);
foreach (var info in resourceFiles)
{
TreeNode fSubNode = new TreeNode(info.Name, info.FullName);
node.ChildNodes.Add(fSubNode);
}
}
return true;
}
private void BindResourceData(string resourcePath)
{
try
{
XDocument docEn = XDocument.Load(resourcePath);
var resourceData = (from data in docEn.Descendants().Elements("data")
where data.Element("value").Value.Trim() != string.Empty &&
!data.Attribute("name").Value.EndsWith(".Value", StringComparison.InvariantCultureIgnoreCase) &&
!data.Attribute("name").Value.EndsWith(".SortExpression", StringComparison.InvariantCultureIgnoreCase)
select new
{
Key = data.Attribute("name").Value,
Values = new KeyValuePair<string, string>[] { new KeyValuePair<string, string>("de-DE", data.Element("value").Value) }.ToList()
}).ToList();
foreach (string culture in otherCultures)
{
//if (culture.CultureCode == "de-DE") continue;
string path = resourcePath.Replace(".resx", "." + culture + ".resx");
XDocument doc = null;
if (File.Exists(path))
doc = XDocument.Load(path);
foreach (var resourceItem in resourceData)
{
if (doc == null)
{
resourceItem.Values.Add(new KeyValuePair<string, string>(culture, null));
continue;
}
XElement ele = doc.Descendants("data").SingleOrDefault(d => d.Attribute("name").Value == resourceItem.Key);
if (ele == null)
resourceItem.Values.Add(new KeyValuePair<string, string>(culture, null));
else
resourceItem.Values.Add(new KeyValuePair<string, string>(culture, ele.Element("value").Value));
}
}
lvResource.DataSource = resourceData;
lvResource.DataBind();
divButton.Visible = true;
}
catch (Exception ex)
{
lbMessage.Text = "<font color='Red'>Fail to load file:" + ex.Message.Replace("'", "") + "</font>";
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
try
{
Repeater rptCulture = lvResource.FindControl("rptCulture") as Repeater;
List<KeyValuePair<string, XDocument>> resourceFiles = new List<KeyValuePair<string, XDocument>>();
string path = null;
foreach (RepeaterItem item in rptCulture.Items)
{
string culture = (item.FindControl("ltlCulture") as Literal).Text;
if (culture == "de-DE")
{
path = Server.MapPath("~/") + ltlResourceFile.Text;
}
else
{
path = Server.MapPath("~/") + ltlResourceFile.Text.Replace(".resx", "." + culture + ".resx");
}
if (!File.Exists(path))
{
File.Copy(path.Replace("." + culture, string.Empty), path);
}
XDocument doc = XDocument.Load(path);
resourceFiles.Add(new KeyValuePair<string, XDocument>(path, doc));
}
XNamespace xml = "http://www.w3.org/XML/1998/namespace";
foreach (ListViewDataItem lvItem in lvResource.Items)
{
Repeater rptResourceValue = lvItem.FindControl("rptResourceValue") as Repeater;
string key = lvResource.DataKeys[lvItem.DisplayIndex].Value.ToString();
for (int i = 0; i < rptResourceValue.Items.Count; i++)
{
string val = (rptResourceValue.Items[i].FindControl("txtValue") as TextBox).Text.Trim();
XElement ele = resourceFiles[i].Value.Descendants("data").SingleOrDefault(d => d.Attribute("name").Value == key);
if (ele == null)
{
ele = new XElement("data", new XAttribute("name", key), new XAttribute(xml + "space", "preserve"), new XElement("value", val));
resourceFiles[i].Value.Root.Add(ele);
}
else
{
ele.Element("value").SetValue(val);
}
}
}
foreach (var kv in resourceFiles)
{
kv.Value.Save(kv.Key);
}
lbMessage.Text = "<font color='Green'>Save successfully!</font>";
}
catch(Exception ex)
{
lbMessage.Text = "<font color='Red'>Fail to save:" + ex.Message.Replace("'", "") + "</font>";
}
}
protected void lvResource_LayoutCreated(object sender, EventArgs e)
{
Repeater rptCulture = lvResource.FindControl("rptCulture") as Repeater;
BindCultureHeader(rptCulture);
}
private void BindCultureHeader(Repeater rptCulture)
{
if (rptCulture != null)
{
var cultureList = otherCultures.ToList();
cultureList.Insert(0, "de-DE");
rptCulture.DataSource = cultureList;
rptCulture.DataBind();
}
}
protected void lvResource_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Repeater rptResourceValue = e.Item.FindControl("rptResourceValue") as Repeater;
List<KeyValuePair<string, string>> values = DataBinder.GetPropertyValue((e.Item as ListViewDataItem).DataItem, "Values") as List<KeyValuePair<string, string>>;
rptResourceValue.DataSource = values;
rptResourceValue.DataBind();
}
}
protected void lvResource_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.EmptyItem)
{
Repeater rptCulture = e.Item.FindControl("rptCulture") as Repeater;
BindCultureHeader(rptCulture);
HtmlTableCell tdEmpty = e.Item.FindControl("tdEmpty") as HtmlTableCell;
tdEmpty.ColSpan = otherCultures.Length + 1;
}
}
protected void rptCulture_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
Literal ltlCultureCode = e.Item.FindControl("ltlCultureCode") as Literal;
ltlCultureCode.Text = e.Item.DataItem.ToString();
}
}
protected void tv_SelectedNodeChanged(object sender, EventArgs e)
{
BindResourceData(tv.SelectedNode.Value);
ltlResourceFile.Text = "App_LocalResources/" + tv.SelectedNode.Text + ".resx";
}
}
<%@ Page Title="" Language="C#" AutoEventWireup="true" CodeFile="ResourceManage.aspx.cs" Inherits="ResourceManage" ValidateRequest="false" culture="auto" meta:resourcekey="PageResource1" uiculture="auto" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<table width="100%" border="0" cellspacing="1" cellpadding="0" style="background-color:#333333">
<tr>
<td style="background-color:#ffffff; width:200px;" valign="top">
<asp:TreeView ID="tv" runat="server"
onselectednodechanged="tv_SelectedNodeChanged"
meta:resourcekey="tvResource1">
</asp:TreeView>
<a href="MailManage.aspx" target="_blank">Mail Manage</a>
</td>
<td style="background-color:#ffffff" valign="top">
<div id='rightContent'>
<div style="padding: 10px;" runat="server" id="divButton">
<asp:Label ID="lbMessage" runat="server" meta:resourcekey="lbMessageResource1"></asp:Label>
<br />
<asp:Button runat="server" ID="btnSave" Text="Save" OnClick="btnSave_Click"
meta:resourcekey="btnSaveResource1" />
Resource file:
<asp:Literal runat="server" ID="ltlResourceFile"
meta:resourcekey="ltlResourceFileResource1" />
</div>
<asp:ListView runat="server" ID="lvResource" DataKeyNames="Key" OnLayoutCreated="lvResource_LayoutCreated"
OnItemDataBound="lvResource_ItemDataBound" OnItemCreated="lvResource_ItemCreated">
<LayoutTemplate>
<table cellpadding="0" cellspacing="2" border="0" class="resultTable">
<thead>
<tr>
<asp:Repeater runat="server" ID="rptCulture">
<ItemTemplate>
<td>
<asp:Literal runat="server" ID="ltlCulture" Text='<%# Container.DataItem %>' />
</td>
</ItemTemplate>
</asp:Repeater>
</tr>
</thead>
<tbody>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</tbody>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr style='<%# Eval("key").ToString().Contains(".value")?"background:#a00":"" %>'>
<asp:Repeater runat="server" ID="rptResourceValue">
<ItemTemplate>
<td>
<asp:TextBox runat="server" ID="txtValue" Text='<%# Eval("Value") %>' TextMode="MultiLine" Rows="5"
Width="400px" meta:resourcekey="txtValueResource1" />
</td>
</ItemTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
<EmptyDataTemplate>
<table cellpadding="0" cellspacing="0" border="0" class="resultTable">
<thead>
<tr>
<asp:Repeater runat="server" ID="rptCulture" OnItemDataBound="rptCulture_ItemDataBound">
<ItemTemplate>
<td>
<asp:Literal runat="server" ID="ltlCultureCode"
meta:resourcekey="ltlCultureCodeResource1" />
</td>
</ItemTemplate>
</asp:Repeater>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2" id="tdEmpty" runat="server" align="center">
No resource data available
</td>
</tr>
</tbody>
</table>
</EmptyDataTemplate>
</asp:ListView>
<br />
</div>
</td>
</tr>
</table>
</form>
</body>
</html>