logging enhancements
This commit is contained in:
@ -6,108 +6,124 @@
|
||||
@inject IPageModuleService PageModuleService
|
||||
@inject IUserService UserService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Date: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@logdate" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Category: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@category" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Level: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@level" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
@if (pagename != "")
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Page: </label>
|
||||
<label class="control-label">Date/Time: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@pagename" disabled />
|
||||
<input class="form-control" @bind="@logdate" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (moduletitle != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Module: </label>
|
||||
<label class="control-label">Level: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@moduletitle" disabled />
|
||||
<input class="form-control" @bind="@level" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (username != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">User: </label>
|
||||
<label class="control-label">Feature: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@username" disabled />
|
||||
<input class="form-control" @bind="@feature" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Template: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@template" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Message: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@message" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(exception))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Exception: </label>
|
||||
<label class="control-label">Function: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@exception" rows="5" disabled />
|
||||
<input class="form-control" @bind="@function" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Properties: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@properties" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Server: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@server" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Category: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@category" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
@if (pagename != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Page: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@pagename" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (moduletitle != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Module: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@moduletitle" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (username != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">User: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@username" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Template: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@template" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Message: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@message" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(exception))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Exception: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@exception" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Properties: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@properties" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Server: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@server" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
@ -115,8 +131,10 @@
|
||||
|
||||
int logid;
|
||||
string logdate = "";
|
||||
string category = "";
|
||||
string level = "";
|
||||
string feature = "";
|
||||
string function = "";
|
||||
string category = "";
|
||||
string pagename = "";
|
||||
string moduletitle = "";
|
||||
string username = "";
|
||||
@ -136,8 +154,10 @@
|
||||
if (log != null)
|
||||
{
|
||||
logdate = log.LogDate.ToString();
|
||||
category = log.Category;
|
||||
level = log.Level;
|
||||
feature = log.Feature;
|
||||
function = log.Function;
|
||||
category = log.Category;
|
||||
if (log.PageId != null)
|
||||
{
|
||||
Page page = await PageService.GetPageAsync(log.PageId.Value);
|
||||
|
@ -19,6 +19,16 @@ else
|
||||
<option value="Error">Error</option>
|
||||
<option value="Critical">Critical</option>
|
||||
</select>
|
||||
<label>Function: </label>
|
||||
<select class="form-control" @onchange="(e => FunctionChanged(e))">
|
||||
<option value="-"><All Functions></option>
|
||||
<option value="Create">Create</option>
|
||||
<option value="Read">Read</option>
|
||||
<option value="Update">Update</option>
|
||||
<option value="Delete">Delete</option>
|
||||
<option value="Security">Security</option>
|
||||
<option value="Other">Other</option>
|
||||
</select>
|
||||
<label>Rows: </label>
|
||||
<select class="form-control" @onchange="(e => RowsChanged(e))">
|
||||
<option value="10">10</option>
|
||||
@ -26,34 +36,44 @@ else
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
</div>
|
||||
@if(Logs.Any())
|
||||
{
|
||||
<Pager Items="@Logs">
|
||||
<Header>
|
||||
<th>Date</th>
|
||||
<th>Category</th>
|
||||
<th>Level</th>
|
||||
<th> </th>
|
||||
<th>Date</th>
|
||||
<th>Level</th>
|
||||
<th>Feature</th>
|
||||
<th>Function</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.LogDate</td>
|
||||
<td>@context.Category</td>
|
||||
<td>@context.Level</td>
|
||||
<td><ActionLink Action="Detail" Parameters="@($"id=" + context.LogId.ToString())" /></td>
|
||||
<td>@context.LogDate</td>
|
||||
<td>@context.Level</td>
|
||||
<td>@context.Feature</td>
|
||||
<td>@context.Function</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p><em>No Logs Match The Criteria Specified</em></p>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string level = "-";
|
||||
string rows = "50";
|
||||
string function = "-";
|
||||
string rows = "10";
|
||||
List<Log> Logs;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Logs = await LogService.GetLogsAsync(PageState.Site.SiteId, ((level == "-") ? "" : level), int.Parse(rows));
|
||||
await GetLogs();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -67,7 +87,7 @@ else
|
||||
try
|
||||
{
|
||||
level = (string)e.Value;
|
||||
Logs = await LogService.GetLogsAsync(PageState.Site.SiteId, ((level == "-") ? "" : level), int.Parse(rows));
|
||||
await GetLogs();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -77,12 +97,12 @@ else
|
||||
}
|
||||
}
|
||||
|
||||
private async void RowsChanged(ChangeEventArgs e)
|
||||
private async void FunctionChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
rows = (string)e.Value;
|
||||
Logs = await LogService.GetLogsAsync(PageState.Site.SiteId, ((level == "-") ? "" : level), int.Parse(rows));
|
||||
function = (string)e.Value;
|
||||
await GetLogs();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -91,4 +111,25 @@ else
|
||||
AddModuleMessage("Error Loading Logs", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async void RowsChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
rows = (string)e.Value;
|
||||
await GetLogs();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Logs {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Logs", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetLogs()
|
||||
{
|
||||
Logs = await LogService.GetLogsAsync(PageState.Site.SiteId, ((level == "-") ? "" : level), ((function == "-") ? "" : function), int.Parse(rows));
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@
|
||||
|
||||
if (PageState.EditMode)
|
||||
{
|
||||
string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameClass(ModuleState.ModuleType) + ",", Action + ",");
|
||||
string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameLastSegment(ModuleState.ModuleType, 0) + ",", Action + ",");
|
||||
Type moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
{
|
||||
|
@ -1,10 +0,0 @@
|
||||
namespace Oqtane.Modules
|
||||
{
|
||||
public enum MessageType
|
||||
{
|
||||
Success,
|
||||
Info,
|
||||
Warning,
|
||||
Error
|
||||
}
|
||||
}
|
@ -135,7 +135,25 @@ namespace Oqtane.Modules
|
||||
{
|
||||
UserId = PageState.User.UserId;
|
||||
}
|
||||
await LoggingService.Log(PageId, ModuleId, UserId, this.GetType().ToString(), level, exception, message, args);
|
||||
string category = this.GetType().AssemblyQualifiedName;
|
||||
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
||||
LogFunction function;
|
||||
switch (PageState.Action)
|
||||
{
|
||||
case "Add":
|
||||
function = LogFunction.Create;
|
||||
break;
|
||||
case "Edit":
|
||||
function = LogFunction.Update;
|
||||
break;
|
||||
case "Delete":
|
||||
function = LogFunction.Delete;
|
||||
break;
|
||||
default:
|
||||
function = LogFunction.Read;
|
||||
break;
|
||||
}
|
||||
await LoggingService.Log(PageId, ModuleId, UserId, category, feature, function, level, exception, message, args);
|
||||
}
|
||||
|
||||
public class Logger
|
||||
|
@ -8,8 +8,8 @@ namespace Oqtane.Services
|
||||
{
|
||||
public interface ILogService
|
||||
{
|
||||
Task<List<Log>> GetLogsAsync(int SiteId, string Level, int Rows);
|
||||
Task<List<Log>> GetLogsAsync(int SiteId, string Level, string Function, int Rows);
|
||||
Task<Log> GetLogAsync(int LogId);
|
||||
Task Log(int? PageId, int? ModuleId, int? UserId, string component, LogLevel level, Exception exception, string message, params object[] args);
|
||||
Task Log(int? PageId, int? ModuleId, int? UserId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args);
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ namespace Oqtane.Services
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "Log"); }
|
||||
}
|
||||
|
||||
public async Task<List<Log>> GetLogsAsync(int SiteId, string Level, int Rows)
|
||||
public async Task<List<Log>> GetLogsAsync(int SiteId, string Level, string Function, int Rows)
|
||||
{
|
||||
return await http.GetJsonAsync<List<Log>>(apiurl + "?siteid=" + SiteId.ToString() + "&level=" + Level + "&rows=" + Rows.ToString());
|
||||
return await http.GetJsonAsync<List<Log>>(apiurl + "?siteid=" + SiteId.ToString() + "&level=" + Level + "&function=" + Function + "&rows=" + Rows.ToString());
|
||||
}
|
||||
|
||||
public async Task<Log> GetLogAsync(int LogId)
|
||||
@ -37,7 +37,7 @@ namespace Oqtane.Services
|
||||
return await http.GetJsonAsync<Log>(apiurl + "/" + LogId.ToString());
|
||||
}
|
||||
|
||||
public async Task Log(int? PageId, int? ModuleId, int? UserId, string category, LogLevel level, Exception exception, string message, params object[] args)
|
||||
public async Task Log(int? PageId, int? ModuleId, int? UserId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args)
|
||||
{
|
||||
Log log = new Log();
|
||||
log.SiteId = sitestate.Alias.SiteId;
|
||||
@ -46,6 +46,8 @@ namespace Oqtane.Services
|
||||
log.UserId = UserId;
|
||||
log.Url = NavigationManager.Uri;
|
||||
log.Category = category;
|
||||
log.Feature = feature;
|
||||
log.Function = Enum.GetName(typeof(LogFunction), function);
|
||||
log.Level = Enum.GetName(typeof(LogLevel), level);
|
||||
if (exception != null)
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ namespace Oqtane.Services
|
||||
{
|
||||
foreach (string themecontrol in theme.ThemeControls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
selectableThemes.Add(themecontrol, theme.Name + " - " + Utilities.GetTypeNameClass(themecontrol));
|
||||
selectableThemes.Add(themecontrol, theme.Name + " - " + Utilities.GetTypeNameLastSegment(themecontrol, 0));
|
||||
}
|
||||
}
|
||||
return selectableThemes;
|
||||
@ -83,7 +83,7 @@ namespace Oqtane.Services
|
||||
{
|
||||
foreach (string panelayout in theme.PaneLayouts.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
selectablePaneLayouts.Add(panelayout, theme.Name + " - " + @Utilities.GetTypeNameClass(panelayout));
|
||||
selectablePaneLayouts.Add(panelayout, theme.Name + " - " + @Utilities.GetTypeNameLastSegment(panelayout, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,7 +97,7 @@ namespace Oqtane.Services
|
||||
{
|
||||
foreach (string container in theme.ContainerControls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
selectableContainers.Add(container, theme.Name + " - " + @Utilities.GetTypeNameClass(container));
|
||||
selectableContainers.Add(container, theme.Name + " - " + @Utilities.GetTypeNameLastSegment(container, 0));
|
||||
}
|
||||
}
|
||||
return selectableContainers;
|
||||
|
@ -48,7 +48,7 @@
|
||||
else
|
||||
{
|
||||
// module does not exist with typename specified
|
||||
message = "Module Does Not Have A Component Named " + Utilities.GetTypeNameClass(typename) + ".razor";
|
||||
message = "Module Does Not Have A Component Named " + Utilities.GetTypeNameLastSegment(typename, 0) + ".razor";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
namespace Oqtane.Shared
|
||||
{
|
||||
public enum Reload
|
||||
{
|
||||
None,
|
||||
Page,
|
||||
Site,
|
||||
Application
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Oqtane.Shared
|
||||
{
|
||||
public class Utilities
|
||||
{
|
||||
|
||||
public static string NavigateUrl(string alias, string path, string parameters, Reload reload)
|
||||
{
|
||||
string url = "";
|
||||
if (alias != "")
|
||||
{
|
||||
url += alias + "/";
|
||||
}
|
||||
if (path != "" && path != "/")
|
||||
{
|
||||
url += path + "/";
|
||||
}
|
||||
if (url.EndsWith("/"))
|
||||
{
|
||||
url = url.Substring(0, url.Length - 1);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(parameters))
|
||||
{
|
||||
url += "?" + parameters;
|
||||
}
|
||||
if (reload != Reload.None)
|
||||
{
|
||||
url += ((string.IsNullOrEmpty(parameters)) ? "?" : "&") + "reload=" + ((int)reload).ToString();
|
||||
}
|
||||
if (!url.StartsWith("/"))
|
||||
{
|
||||
url = "/" + url;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
|
||||
{
|
||||
string url = NavigateUrl(alias, path, "", Reload.None);
|
||||
if (url == "/") url = "";
|
||||
if (moduleid != -1)
|
||||
{
|
||||
url += "/" + moduleid.ToString();
|
||||
}
|
||||
if (moduleid != -1 && action != "")
|
||||
{
|
||||
url += "/" + action;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(parameters))
|
||||
{
|
||||
url += "?" + parameters;
|
||||
}
|
||||
if (!url.StartsWith("/"))
|
||||
{
|
||||
url = "/" + url;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
public static string GetTypeName(string fullyqualifiedtypename)
|
||||
{
|
||||
if (fullyqualifiedtypename.Contains(","))
|
||||
{
|
||||
return fullyqualifiedtypename.Substring(0, fullyqualifiedtypename.IndexOf(","));
|
||||
}
|
||||
else
|
||||
{
|
||||
return fullyqualifiedtypename;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetTypeNameClass(string typename)
|
||||
{
|
||||
if (typename.Contains(","))
|
||||
{
|
||||
typename = typename.Substring(0, typename.IndexOf(","));
|
||||
}
|
||||
string[] fragments = typename.Split('.');
|
||||
return fragments[fragments.Length - 1];
|
||||
}
|
||||
|
||||
public static string GetFriendlyUrl(string text)
|
||||
{
|
||||
string result = "";
|
||||
if (text != null)
|
||||
{
|
||||
var normalizedString = text.ToLowerInvariant().Normalize(NormalizationForm.FormD);
|
||||
var stringBuilder = new StringBuilder();
|
||||
var stringLength = normalizedString.Length;
|
||||
var prevdash = false;
|
||||
char c;
|
||||
for (int i = 0; i < stringLength; i++)
|
||||
{
|
||||
c = normalizedString[i];
|
||||
switch (CharUnicodeInfo.GetUnicodeCategory(c))
|
||||
{
|
||||
case UnicodeCategory.LowercaseLetter:
|
||||
case UnicodeCategory.UppercaseLetter:
|
||||
case UnicodeCategory.DecimalDigitNumber:
|
||||
if (c < 128)
|
||||
stringBuilder.Append(c);
|
||||
else
|
||||
stringBuilder.Append(RemapInternationalCharToAscii(c));
|
||||
prevdash = false;
|
||||
break;
|
||||
case UnicodeCategory.SpaceSeparator:
|
||||
case UnicodeCategory.ConnectorPunctuation:
|
||||
case UnicodeCategory.DashPunctuation:
|
||||
case UnicodeCategory.OtherPunctuation:
|
||||
case UnicodeCategory.MathSymbol:
|
||||
if (!prevdash)
|
||||
{
|
||||
stringBuilder.Append('-');
|
||||
prevdash = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = stringBuilder.ToString().Trim('-');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string RemapInternationalCharToAscii(char c)
|
||||
{
|
||||
string s = c.ToString().ToLowerInvariant();
|
||||
if ("àåáâäãåą".Contains(s))
|
||||
{
|
||||
return "a";
|
||||
}
|
||||
else if ("èéêëę".Contains(s))
|
||||
{
|
||||
return "e";
|
||||
}
|
||||
else if ("ìíîïı".Contains(s))
|
||||
{
|
||||
return "i";
|
||||
}
|
||||
else if ("òóôõöøőð".Contains(s))
|
||||
{
|
||||
return "o";
|
||||
}
|
||||
else if ("ùúûüŭů".Contains(s))
|
||||
{
|
||||
return "u";
|
||||
}
|
||||
else if ("çćčĉ".Contains(s))
|
||||
{
|
||||
return "c";
|
||||
}
|
||||
else if ("żźž".Contains(s))
|
||||
{
|
||||
return "z";
|
||||
}
|
||||
else if ("śşšŝ".Contains(s))
|
||||
{
|
||||
return "s";
|
||||
}
|
||||
else if ("ñń".Contains(s))
|
||||
{
|
||||
return "n";
|
||||
}
|
||||
else if ("ýÿ".Contains(s))
|
||||
{
|
||||
return "y";
|
||||
}
|
||||
else if ("ğĝ".Contains(s))
|
||||
{
|
||||
return "g";
|
||||
}
|
||||
else if (c == 'ř')
|
||||
{
|
||||
return "r";
|
||||
}
|
||||
else if (c == 'ł')
|
||||
{
|
||||
return "l";
|
||||
}
|
||||
else if (c == 'đ')
|
||||
{
|
||||
return "d";
|
||||
}
|
||||
else if (c == 'ß')
|
||||
{
|
||||
return "ss";
|
||||
}
|
||||
else if (c == 'þ')
|
||||
{
|
||||
return "th";
|
||||
}
|
||||
else if (c == 'ĥ')
|
||||
{
|
||||
return "h";
|
||||
}
|
||||
else if (c == 'ĵ')
|
||||
{
|
||||
return "j";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user