Add StringUsageReporter
StringUsageReporter reports usages of localization strings in the web application and can also list all unused strings
This commit is contained in:
parent
98bb84e82a
commit
aa434d591e
1348
MediaBrowser.Tests/ConsistencyTests/Resources/SampleTransformed.htm
Normal file
1348
MediaBrowser.Tests/ConsistencyTests/Resources/SampleTransformed.htm
Normal file
File diff suppressed because it is too large
Load Diff
145
MediaBrowser.Tests/ConsistencyTests/Resources/StringCheck.xslt
Normal file
145
MediaBrowser.Tests/ConsistencyTests/Resources/StringCheck.xslt
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- DWXMLSource="StringCheckSample.xml" -->
|
||||||
|
<!DOCTYPE xsl:stylesheet [
|
||||||
|
<!ENTITY nbsp " ">
|
||||||
|
<!ENTITY copy "©">
|
||||||
|
<!ENTITY reg "®">
|
||||||
|
<!ENTITY trade "™">
|
||||||
|
<!ENTITY mdash "—">
|
||||||
|
<!ENTITY ldquo "“">
|
||||||
|
<!ENTITY rdquo "”">
|
||||||
|
<!ENTITY pound "£">
|
||||||
|
<!ENTITY yen "¥">
|
||||||
|
<!ENTITY euro "€">
|
||||||
|
]>
|
||||||
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||||
|
<xsl:output method="html" encoding="utf-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
|
||||||
|
<xsl:template match="/">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<title>
|
||||||
|
<xsl:value-of select="StringUsages/@ReportTitle"/>
|
||||||
|
</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background: #F3F3F4;
|
||||||
|
color: #1E1E1F;
|
||||||
|
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
padding: 10px 0px 10px 10px;
|
||||||
|
font-size: 21pt;
|
||||||
|
background-color: #E2E2E2;
|
||||||
|
border-bottom: 1px #C1C1C2 solid;
|
||||||
|
color: #201F20;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 18pt;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 15px 0 5px 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 15pt;
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px 0 5px 0;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
/* Color all hyperlinks one color */
|
||||||
|
a {
|
||||||
|
color: #1382CE;
|
||||||
|
}
|
||||||
|
/* Table styles */
|
||||||
|
table {
|
||||||
|
border-spacing: 0 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
table th {
|
||||||
|
background: #E7E7E8;
|
||||||
|
text-align: left;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 3px 6px 3px 6px;
|
||||||
|
border: 1px solid #CBCBCB;
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 3px 6px 5px 5px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 1px solid #CBCBCB;
|
||||||
|
background: #F7F7F8;
|
||||||
|
}
|
||||||
|
/* Local link is a style for hyperlinks that link to file:/// content, there are lots so color them as 'normal' text until the user mouse overs */
|
||||||
|
.localLink {
|
||||||
|
color: #1E1E1F;
|
||||||
|
background: #EEEEED;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.localLink:hover {
|
||||||
|
color: #1382CE;
|
||||||
|
background: #FFFF99;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.baseCell {
|
||||||
|
width: 100%;
|
||||||
|
color: #427A9F;
|
||||||
|
}
|
||||||
|
.stringCell {
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
.tokenCell {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.occurrence {
|
||||||
|
padding-left: 40px;
|
||||||
|
}
|
||||||
|
.block {
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
/* Padding around the content after the h1 */
|
||||||
|
#content {
|
||||||
|
padding: 0px 12px 12px 12px;
|
||||||
|
}
|
||||||
|
#messages table {
|
||||||
|
width: 97%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
<xsl:value-of select="StringUsages/@ReportTitle"/>
|
||||||
|
</h1>
|
||||||
|
<div id="content">
|
||||||
|
<h2>Strings</h2>
|
||||||
|
<div id="messages">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<xsl:for-each select="StringUsages/Dictionary">
|
||||||
|
<tr>
|
||||||
|
<th class="baseCell"> <div class="stringCell">
|
||||||
|
<div class="block tokenCell"><strong><xsl:value-of select="@Token"/></strong>: "</div>
|
||||||
|
<div class="block"><xsl:value-of select="@Text"/>"</div>
|
||||||
|
</div></th>
|
||||||
|
</tr>
|
||||||
|
<xsl:for-each select="Occurence">
|
||||||
|
<xsl:variable name="hyperlink"><xsl:value-of select="@FullPath" /></xsl:variable>
|
||||||
|
<tr>
|
||||||
|
<td class="baseCell occurrence"><a href="{@FullPath}"><xsl:value-of select="@FileName"/>:<xsl:value-of select="@LineNumber"/></a></td>
|
||||||
|
</tr>
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:for-each>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>
|
|
@ -0,0 +1,239 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<?xml-stylesheet type="text/xsl" href="StringCheck.xslt"?>
|
||||||
|
<StringUsages Mode="All">
|
||||||
|
<Dictionary Token="LabelExit" Text="Exit" />
|
||||||
|
<Dictionary Token="LabelVisitCommunity" Text="Visit Community" />
|
||||||
|
<Dictionary Token="LabelGithub" Text="Github" />
|
||||||
|
<Dictionary Token="LabelSwagger" Text="Swagger" />
|
||||||
|
<Dictionary Token="LabelStandard" Text="Standard" />
|
||||||
|
<Dictionary Token="LabelApiDocumentation" Text="Api Documentation" />
|
||||||
|
<Dictionary Token="LabelDeveloperResources" Text="Developer Resources" />
|
||||||
|
<Dictionary Token="LabelBrowseLibrary" Text="Browse Library" />
|
||||||
|
<Dictionary Token="LabelConfigureServer" Text="Configure Emby" />
|
||||||
|
<Dictionary Token="LabelOpenLibraryViewer" Text="Open Library Viewer" />
|
||||||
|
<Dictionary Token="LabelRestartServer" Text="Restart Server" />
|
||||||
|
<Dictionary Token="LabelShowLogWindow" Text="Show Log Window" />
|
||||||
|
<Dictionary Token="LabelPrevious" Text="Previous">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="21" />
|
||||||
|
<Occurence FileName="\wizardcomponents.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardcomponents.html" LineNumber="54" />
|
||||||
|
<Occurence FileName="\wizardfinish.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardfinish.html" LineNumber="40" />
|
||||||
|
<Occurence FileName="\wizardlibrary.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardlibrary.html" LineNumber="19" />
|
||||||
|
<Occurence FileName="\wizardlivetvguide.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardlivetvguide.html" LineNumber="30" />
|
||||||
|
<Occurence FileName="\wizardlivetvtuner.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardlivetvtuner.html" LineNumber="31" />
|
||||||
|
<Occurence FileName="\wizardservice.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardservice.html" LineNumber="17" />
|
||||||
|
<Occurence FileName="\wizardsettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardsettings.html" LineNumber="32" />
|
||||||
|
<Occurence FileName="\wizarduser.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizarduser.html" LineNumber="27" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelFinish" Text="Finish">
|
||||||
|
<Occurence FileName="\wizardfinish.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardfinish.html" LineNumber="41" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelNext" Text="Next">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="22" />
|
||||||
|
<Occurence FileName="\wizardcomponents.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardcomponents.html" LineNumber="55" />
|
||||||
|
<Occurence FileName="\wizardlibrary.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardlibrary.html" LineNumber="20" />
|
||||||
|
<Occurence FileName="\wizardlivetvguide.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardlivetvguide.html" LineNumber="31" />
|
||||||
|
<Occurence FileName="\wizardlivetvtuner.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardlivetvtuner.html" LineNumber="32" />
|
||||||
|
<Occurence FileName="\wizardservice.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardservice.html" LineNumber="18" />
|
||||||
|
<Occurence FileName="\wizardsettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardsettings.html" LineNumber="33" />
|
||||||
|
<Occurence FileName="\wizardstart.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardstart.html" LineNumber="25" />
|
||||||
|
<Occurence FileName="\wizarduser.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizarduser.html" LineNumber="28" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelYoureDone" Text="You're Done!">
|
||||||
|
<Occurence FileName="\wizardfinish.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardfinish.html" LineNumber="7" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="WelcomeToProject" Text="Welcome to Emby!">
|
||||||
|
<Occurence FileName="\wizardstart.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardstart.html" LineNumber="10" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ThisWizardWillGuideYou" Text="This wizard will help guide you through the setup process. To begin, please select your preferred language.">
|
||||||
|
<Occurence FileName="\wizardstart.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardstart.html" LineNumber="16" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="TellUsAboutYourself" Text="Tell us about yourself">
|
||||||
|
<Occurence FileName="\wizarduser.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizarduser.html" LineNumber="8" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonQuickStartGuide" Text="Quick start guide">
|
||||||
|
<Occurence FileName="\wizardstart.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardstart.html" LineNumber="12" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelYourFirstName" Text="Your first name:">
|
||||||
|
<Occurence FileName="\wizarduser.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizarduser.html" LineNumber="14" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="MoreUsersCanBeAddedLater" Text="More users can be added later within the Dashboard.">
|
||||||
|
<Occurence FileName="\wizarduser.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizarduser.html" LineNumber="15" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="UserProfilesIntro" Text="Emby includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.">
|
||||||
|
<Occurence FileName="\wizarduser.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizarduser.html" LineNumber="11" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelWindowsService" Text="Windows Service">
|
||||||
|
<Occurence FileName="\wizardservice.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardservice.html" LineNumber="7" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="AWindowsServiceHasBeenInstalled" Text="A Windows Service has been installed.">
|
||||||
|
<Occurence FileName="\wizardservice.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardservice.html" LineNumber="10" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="WindowsServiceIntro1" Text="Emby Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.">
|
||||||
|
<Occurence FileName="\wizardservice.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardservice.html" LineNumber="12" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="WindowsServiceIntro2" Text="If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. When running as a service, you will need to ensure that the service account has access to your media folders.">
|
||||||
|
<Occurence FileName="\wizardservice.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardservice.html" LineNumber="14" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="WizardCompleted" Text="That's all we need for now. Emby has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish</b> to view the <b>Server Dashboard</b>.">
|
||||||
|
<Occurence FileName="\wizardfinish.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardfinish.html" LineNumber="10" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelConfigureSettings" Text="Configure settings">
|
||||||
|
<Occurence FileName="\wizardsettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardsettings.html" LineNumber="8" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelEnableVideoImageExtraction" Text="Enable video image extraction" />
|
||||||
|
<Dictionary Token="VideoImageExtractionHelp" Text="For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation." />
|
||||||
|
<Dictionary Token="LabelEnableChapterImageExtractionForMovies" Text="Extract chapter image extraction for Movies" />
|
||||||
|
<Dictionary Token="LabelChapterImageExtractionForMoviesHelp" Text="Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours." />
|
||||||
|
<Dictionary Token="LabelEnableAutomaticPortMapping" Text="Enable automatic port mapping" />
|
||||||
|
<Dictionary Token="LabelEnableAutomaticPortMappingHelp" Text="UPnP allows automated router configuration for easy remote access. This may not work with some router models." />
|
||||||
|
<Dictionary Token="HeaderTermsOfService" Text="Emby Terms of Service">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="9" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="MessagePleaseAcceptTermsOfService" Text="Please accept the terms of service and privacy policy before continuing.">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="12" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="OptionIAcceptTermsOfService" Text="I accept the terms of service">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="17" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonPrivacyPolicy" Text="Privacy policy">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="14" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonTermsOfService" Text="Terms of Service">
|
||||||
|
<Occurence FileName="\wizardagreement.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\wizardagreement.html" LineNumber="15" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderDeveloperOptions" Text="Developer Options">
|
||||||
|
<Occurence FileName="\dashboardgeneral.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboardgeneral.html" LineNumber="108" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="OptionEnableWebClientResponseCache" Text="Enable web response caching">
|
||||||
|
<Occurence FileName="\dashboardgeneral.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboardgeneral.html" LineNumber="112" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="OptionDisableForDevelopmentHelp" Text="Configure these as needed for web development purposes.">
|
||||||
|
<Occurence FileName="\dashboardgeneral.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboardgeneral.html" LineNumber="119" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="OptionEnableWebClientResourceMinification" Text="Enable web resource minification">
|
||||||
|
<Occurence FileName="\dashboardgeneral.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboardgeneral.html" LineNumber="116" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelDashboardSourcePath" Text="Web client source path:">
|
||||||
|
<Occurence FileName="\dashboardgeneral.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboardgeneral.html" LineNumber="124" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LabelDashboardSourcePathHelp" Text="If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.">
|
||||||
|
<Occurence FileName="\dashboardgeneral.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboardgeneral.html" LineNumber="126" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonConvertMedia" Text="Convert media">
|
||||||
|
<Occurence FileName="\syncactivity.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\syncactivity.html" LineNumber="22" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonOrganize" Text="Organize">
|
||||||
|
<Occurence FileName="\autoorganizelog.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\autoorganizelog.html" LineNumber="8" />
|
||||||
|
<Occurence FileName="\scripts\autoorganizelog.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\autoorganizelog.js" LineNumber="293" />
|
||||||
|
<Occurence FileName="\scripts\autoorganizelog.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\autoorganizelog.js" LineNumber="294" />
|
||||||
|
<Occurence FileName="\scripts\autoorganizelog.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\autoorganizelog.js" LineNumber="296" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="LinkedToEmbyConnect" Text="Linked to Emby Connect" />
|
||||||
|
<Dictionary Token="HeaderSupporterBenefits" Text="Emby Premiere Benefits" />
|
||||||
|
<Dictionary Token="HeaderAddUser" Text="Add User" />
|
||||||
|
<Dictionary Token="LabelAddConnectSupporterHelp" Text="To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page." />
|
||||||
|
<Dictionary Token="LabelPinCode" Text="Pin code:" />
|
||||||
|
<Dictionary Token="OptionHideWatchedContentFromLatestMedia" Text="Hide watched content from latest media">
|
||||||
|
<Occurence FileName="\mypreferenceshome.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\mypreferenceshome.html" LineNumber="114" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderSync" Text="Sync">
|
||||||
|
<Occurence FileName="\mysyncsettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\mysyncsettings.html" LineNumber="7" />
|
||||||
|
<Occurence FileName="\scripts\registrationservices.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\registrationservices.js" LineNumber="175" />
|
||||||
|
<Occurence FileName="\useredit.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\useredit.html" LineNumber="82" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonOk" Text="Ok">
|
||||||
|
<Occurence FileName="\components\directorybrowser\directorybrowser.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\directorybrowser\directorybrowser.js" LineNumber="147" />
|
||||||
|
<Occurence FileName="\components\fileorganizer\fileorganizer.template.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\fileorganizer\fileorganizer.template.html" LineNumber="45" />
|
||||||
|
<Occurence FileName="\components\medialibrarycreator\medialibrarycreator.template.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\medialibrarycreator\medialibrarycreator.template.html" LineNumber="30" />
|
||||||
|
<Occurence FileName="\components\metadataeditor\personeditor.template.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\metadataeditor\personeditor.template.html" LineNumber="33" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="372" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="453" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="504" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="542" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="590" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="630" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="661" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="706" />
|
||||||
|
<Occurence FileName="\nowplaying.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\nowplaying.html" LineNumber="113" />
|
||||||
|
<Occurence FileName="\scripts\ratingdialog.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\ratingdialog.js" LineNumber="42" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonCancel" Text="Cancel">
|
||||||
|
<Occurence FileName="\components\tvproviders\schedulesdirect.template.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\tvproviders\schedulesdirect.template.html" LineNumber="68" />
|
||||||
|
<Occurence FileName="\components\tvproviders\xmltv.template.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\tvproviders\xmltv.template.html" LineNumber="48" />
|
||||||
|
<Occurence FileName="\connectlogin.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\connectlogin.html" LineNumber="74" />
|
||||||
|
<Occurence FileName="\connectlogin.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\connectlogin.html" LineNumber="108" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="325" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="375" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="456" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="507" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="545" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="593" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="633" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="664" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="709" />
|
||||||
|
<Occurence FileName="\forgotpassword.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\forgotpassword.html" LineNumber="23" />
|
||||||
|
<Occurence FileName="\forgotpasswordpin.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\forgotpasswordpin.html" LineNumber="22" />
|
||||||
|
<Occurence FileName="\livetvseriestimer.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\livetvseriestimer.html" LineNumber="62" />
|
||||||
|
<Occurence FileName="\livetvtunerprovider-hdhomerun.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\livetvtunerprovider-hdhomerun.html" LineNumber="35" />
|
||||||
|
<Occurence FileName="\livetvtunerprovider-m3u.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\livetvtunerprovider-m3u.html" LineNumber="19" />
|
||||||
|
<Occurence FileName="\livetvtunerprovider-satip.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\livetvtunerprovider-satip.html" LineNumber="65" />
|
||||||
|
<Occurence FileName="\login.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\login.html" LineNumber="27" />
|
||||||
|
<Occurence FileName="\notificationsetting.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\notificationsetting.html" LineNumber="64" />
|
||||||
|
<Occurence FileName="\scheduledtask.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scheduledtask.html" LineNumber="85" />
|
||||||
|
<Occurence FileName="\scripts\librarylist.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\librarylist.js" LineNumber="349" />
|
||||||
|
<Occurence FileName="\scripts\mediacontroller.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\mediacontroller.js" LineNumber="167" />
|
||||||
|
<Occurence FileName="\scripts\mediacontroller.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\mediacontroller.js" LineNumber="436" />
|
||||||
|
<Occurence FileName="\scripts\ratingdialog.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\ratingdialog.js" LineNumber="43" />
|
||||||
|
<Occurence FileName="\scripts\site.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\site.js" LineNumber="1025" />
|
||||||
|
<Occurence FileName="\scripts\userprofilespage.js" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scripts\userprofilespage.js" LineNumber="198" />
|
||||||
|
<Occurence FileName="\syncsettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\syncsettings.html" LineNumber="43" />
|
||||||
|
<Occurence FileName="\useredit.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\useredit.html" LineNumber="111" />
|
||||||
|
<Occurence FileName="\userlibraryaccess.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\userlibraryaccess.html" LineNumber="57" />
|
||||||
|
<Occurence FileName="\usernew.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\usernew.html" LineNumber="45" />
|
||||||
|
<Occurence FileName="\userparentalcontrol.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\userparentalcontrol.html" LineNumber="101" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="ButtonExit" Text="Exit" />
|
||||||
|
<Dictionary Token="ButtonNew" Text="New">
|
||||||
|
<Occurence FileName="\components\fileorganizer\fileorganizer.template.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\components\fileorganizer\fileorganizer.template.html" LineNumber="18" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="107" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="278" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="290" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="296" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="302" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="308" />
|
||||||
|
<Occurence FileName="\dlnaprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofile.html" LineNumber="314" />
|
||||||
|
<Occurence FileName="\dlnaprofiles.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dlnaprofiles.html" LineNumber="14" />
|
||||||
|
<Occurence FileName="\serversecurity.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\serversecurity.html" LineNumber="8" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderTaskTriggers" Text="Task Triggers">
|
||||||
|
<Occurence FileName="\scheduledtask.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\scheduledtask.html" LineNumber="11" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderTV" Text="TV">
|
||||||
|
<Occurence FileName="\librarysettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\librarysettings.html" LineNumber="113" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderAudio" Text="Audio">
|
||||||
|
<Occurence FileName="\librarysettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\librarysettings.html" LineNumber="39" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderVideo" Text="Video">
|
||||||
|
<Occurence FileName="\librarysettings.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\librarysettings.html" LineNumber="50" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderPaths" Text="Paths">
|
||||||
|
<Occurence FileName="\dashboard.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\dashboard.html" LineNumber="92" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="CategorySync" Text="Sync" />
|
||||||
|
<Dictionary Token="TabPlaylist" Text="Playlist">
|
||||||
|
<Occurence FileName="\nowplaying.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\nowplaying.html" LineNumber="20" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderEasyPinCode" Text="Easy Pin Code">
|
||||||
|
<Occurence FileName="\myprofile.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\myprofile.html" LineNumber="69" />
|
||||||
|
<Occurence FileName="\userpassword.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\userpassword.html" LineNumber="42" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderGrownupsOnly" Text="Grown-ups Only!" />
|
||||||
|
<Dictionary Token="DividerOr" Text="-- or --" />
|
||||||
|
<Dictionary Token="HeaderInstalledServices" Text="Installed Services">
|
||||||
|
<Occurence FileName="\appservices.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\appservices.html" LineNumber="6" />
|
||||||
|
</Dictionary>
|
||||||
|
<Dictionary Token="HeaderAvailableServices" Text="Available Services">
|
||||||
|
<Occurence FileName="\appservices.html" FullPath="F:\Projects\Softworkz_Emby\Emby\MediaBrowser.WebDashboard\dashboard-ui\appservices.html" LineNumber="11" />
|
||||||
|
</Dictionary>
|
||||||
|
</StringUsages>
|
260
MediaBrowser.Tests/ConsistencyTests/StringUsageReporter.cs
Normal file
260
MediaBrowser.Tests/ConsistencyTests/StringUsageReporter.cs
Normal file
|
@ -0,0 +1,260 @@
|
||||||
|
using MediaBrowser.Tests.ConsistencyTests.TextIndexing;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Tests.ConsistencyTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class contains tests for reporting the usage of localization string tokens
|
||||||
|
/// in the dashboard-ui or similar.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>Run one of the two tests using Visual Studio's "Test Explorer":</para>
|
||||||
|
/// <para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item><see cref="ReportStringUsage"/></item>
|
||||||
|
/// <item><see cref="ReportUnusedStrings"/></item>
|
||||||
|
/// </list>
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// On successful run, the bottom section of the test explorer will contain a link "Output".
|
||||||
|
/// This link will open the test results, displaying the trace and two attachment links.
|
||||||
|
/// One link will open the output folder, the other link will open the output xml file.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The output xml file contains a stylesheet link to render the results as html.
|
||||||
|
/// How that works depends on the default application configured for XML files:
|
||||||
|
/// </para>
|
||||||
|
/// <para><list type="bullet">
|
||||||
|
/// <item><term>Visual Studio</term>
|
||||||
|
/// <description>Will open in XML source view. To view the html result, click menu
|
||||||
|
/// 'XML' => 'Start XSLT without debugging'</description></item>
|
||||||
|
/// <item><term>Internet Explorer</term>
|
||||||
|
/// <description>XSL transform will be applied automatically.</description></item>
|
||||||
|
/// <item><term>Firefox</term>
|
||||||
|
/// <description>XSL transform will be applied automatically.</description></item>
|
||||||
|
/// <item><term>Chrome</term>
|
||||||
|
/// <description>Does not work. Chrome is unable/unwilling to apply xslt transforms from local files.</description></item>
|
||||||
|
/// </list></para>
|
||||||
|
/// </remarks>
|
||||||
|
[TestClass]
|
||||||
|
public class StringUsageReporter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Root path of the web application
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Can be an absolute path or a path relative to the binaries folder (bin\Debug).
|
||||||
|
/// </remarks>
|
||||||
|
public const string WebFolder = @"..\..\..\MediaBrowser.WebDashboard\dashboard-ui";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the strings file, relative to <see cref="WebFolder"/>.
|
||||||
|
/// </summary>
|
||||||
|
public const string StringsFile = @"strings\en-US.json";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the output folder
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Can be an absolute path or a path relative to the binaries folder (bin\Debug).
|
||||||
|
/// Important: When changing the output path, make sure that "StringCheck.xslt" is present
|
||||||
|
/// to make the XML transform work.
|
||||||
|
/// </remarks>
|
||||||
|
public const string OutputPath = @".";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of file extension to search.
|
||||||
|
/// </summary>
|
||||||
|
public static string[] TargetExtensions = new[] { "js", "html" };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of paths to exclude from search.
|
||||||
|
/// </summary>
|
||||||
|
public static string[] ExcludePaths = new[] { @"\bower_components\", @"\thirdparty\" };
|
||||||
|
|
||||||
|
private TestContext testContextInstance;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///Gets or sets the test context which provides
|
||||||
|
///information about and functionality for the current test run.
|
||||||
|
///</summary>
|
||||||
|
public TestContext TestContext
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return testContextInstance;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
testContextInstance = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ReportStringUsage()
|
||||||
|
{
|
||||||
|
this.CheckDashboardStrings(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ReportUnusedStrings()
|
||||||
|
{
|
||||||
|
this.CheckDashboardStrings(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckDashboardStrings(Boolean unusedOnly)
|
||||||
|
{
|
||||||
|
// Init Folders
|
||||||
|
var currentDir = System.IO.Directory.GetCurrentDirectory();
|
||||||
|
Trace("CurrentDir: {0}", currentDir);
|
||||||
|
|
||||||
|
var rootFolderInfo = ResolveFolder(currentDir, WebFolder);
|
||||||
|
Trace("Web Root: {0}", rootFolderInfo.FullName);
|
||||||
|
|
||||||
|
var outputFolderInfo = ResolveFolder(currentDir, OutputPath);
|
||||||
|
Trace("Output Path: {0}", outputFolderInfo.FullName);
|
||||||
|
|
||||||
|
// Load Strings
|
||||||
|
var stringsFileName = Path.Combine(rootFolderInfo.FullName, StringsFile);
|
||||||
|
|
||||||
|
if (!File.Exists(stringsFileName))
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("Strings file not found: {0}", stringsFileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineNumbers;
|
||||||
|
var stringsDic = this.CreateStringsDictionary(new FileInfo(stringsFileName), out lineNumbers);
|
||||||
|
|
||||||
|
Trace("Loaded {0} strings from strings file containing {1} lines", stringsDic.Count, lineNumbers);
|
||||||
|
|
||||||
|
var allFiles = rootFolderInfo.GetFiles("*", SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
var filteredFiles1 = allFiles.Where(f => TargetExtensions.Any(e => f.Name.EndsWith(e)));
|
||||||
|
var filteredFiles2 = filteredFiles1.Where(f => !ExcludePaths.Any(p => f.FullName.Contains(p)));
|
||||||
|
|
||||||
|
var selectedFiles = filteredFiles2.OrderBy(f => f.FullName).ToList();
|
||||||
|
|
||||||
|
var wordIndex = IndexBuilder.BuildIndexFromFiles(selectedFiles, rootFolderInfo.FullName);
|
||||||
|
|
||||||
|
Trace("Created word index from {0} files containing {1} individual words", selectedFiles.Count, wordIndex.Keys.Count);
|
||||||
|
|
||||||
|
var outputFileName = Path.Combine(outputFolderInfo.FullName, string.Format("StringCheck_{0:yyyyMMddHHmmss}.xml", DateTime.Now));
|
||||||
|
var settings = new XmlWriterSettings
|
||||||
|
{
|
||||||
|
Indent = true,
|
||||||
|
Encoding = Encoding.UTF8,
|
||||||
|
WriteEndDocumentOnClose = true
|
||||||
|
};
|
||||||
|
|
||||||
|
Trace("Output file: {0}", outputFileName);
|
||||||
|
|
||||||
|
using (XmlWriter writer = XmlWriter.Create(outputFileName, settings))
|
||||||
|
{
|
||||||
|
writer.WriteStartDocument(true);
|
||||||
|
|
||||||
|
// Write the Processing Instruction node.
|
||||||
|
string xslText = "type=\"text/xsl\" href=\"StringCheck.xslt\"";
|
||||||
|
writer.WriteProcessingInstruction("xml-stylesheet", xslText);
|
||||||
|
|
||||||
|
writer.WriteStartElement("StringUsages");
|
||||||
|
writer.WriteAttributeString("ReportTitle", unusedOnly ? "Unused Strings Report" : "String Usage Report");
|
||||||
|
writer.WriteAttributeString("Mode", unusedOnly ? "UnusedOnly" : "All");
|
||||||
|
|
||||||
|
foreach (var kvp in stringsDic)
|
||||||
|
{
|
||||||
|
var occurences = wordIndex.Find(kvp.Key);
|
||||||
|
|
||||||
|
if (occurences == null || !unusedOnly)
|
||||||
|
{
|
||||||
|
////Trace("{0}: {1}", kvp.Key, kvp.Value);
|
||||||
|
writer.WriteStartElement("Dictionary");
|
||||||
|
writer.WriteAttributeString("Token", kvp.Key);
|
||||||
|
writer.WriteAttributeString("Text", kvp.Value);
|
||||||
|
|
||||||
|
if (occurences != null && !unusedOnly)
|
||||||
|
{
|
||||||
|
foreach (var occurence in occurences)
|
||||||
|
{
|
||||||
|
writer.WriteStartElement("Occurence");
|
||||||
|
writer.WriteAttributeString("FileName", occurence.FileName);
|
||||||
|
writer.WriteAttributeString("FullPath", occurence.FullPath);
|
||||||
|
writer.WriteAttributeString("LineNumber", occurence.LineNumber.ToString());
|
||||||
|
writer.WriteEndElement();
|
||||||
|
////Trace(" {0}:{1}", occurence.FileName, occurence.LineNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestContext.AddResultFile(outputFileName);
|
||||||
|
TestContext.AddResultFile(outputFolderInfo.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SortedDictionary<string, string> CreateStringsDictionary(FileInfo file, out int lineNumbers)
|
||||||
|
{
|
||||||
|
var dic = new SortedDictionary<string, string>();
|
||||||
|
lineNumbers = 0;
|
||||||
|
|
||||||
|
using (var reader = file.OpenText())
|
||||||
|
{
|
||||||
|
while (!reader.EndOfStream)
|
||||||
|
{
|
||||||
|
lineNumbers++;
|
||||||
|
var words = reader
|
||||||
|
.ReadLine()
|
||||||
|
.Split(new[] { "\":" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
|
||||||
|
if (words.Length == 2)
|
||||||
|
{
|
||||||
|
var token = words[0].Replace("\"", string.Empty).Trim();
|
||||||
|
var text = words[1].Replace("\",", string.Empty).Replace("\"", string.Empty).Trim();
|
||||||
|
|
||||||
|
if (dic.Keys.Contains(token))
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("Double string entry found: {0}", token));
|
||||||
|
}
|
||||||
|
|
||||||
|
dic.Add(token, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dic;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DirectoryInfo ResolveFolder(string currentDir, string folderPath)
|
||||||
|
{
|
||||||
|
if (folderPath.IndexOf(@"\:") != 1)
|
||||||
|
{
|
||||||
|
folderPath = Path.Combine(currentDir, folderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
var folderInfo = new DirectoryInfo(folderPath);
|
||||||
|
|
||||||
|
if (!folderInfo.Exists)
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("Folder not found: {0}", folderInfo.FullName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return folderInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Trace(string message, params object[] parameters)
|
||||||
|
{
|
||||||
|
var formatted = string.Format(message, parameters);
|
||||||
|
System.Diagnostics.Trace.WriteLine(formatted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Tests.ConsistencyTests.TextIndexing
|
||||||
|
{
|
||||||
|
public class IndexBuilder
|
||||||
|
{
|
||||||
|
public const int MinumumWordLength = 4;
|
||||||
|
|
||||||
|
public static char[] WordChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
|
||||||
|
|
||||||
|
public static WordIndex BuildIndexFromFiles(IEnumerable<FileInfo> wordFiles, string rootFolderPath)
|
||||||
|
{
|
||||||
|
var index = new WordIndex();
|
||||||
|
|
||||||
|
var wordSeparators = Enumerable.Range(32, 127).Select(e => Convert.ToChar(e)).Where(c => !WordChars.Contains(c)).ToArray();
|
||||||
|
wordSeparators = wordSeparators.Concat(new[] { '\t' }).ToArray(); // add tab
|
||||||
|
|
||||||
|
foreach (var file in wordFiles)
|
||||||
|
{
|
||||||
|
var lineNumber = 1;
|
||||||
|
var displayFileName = file.FullName.Replace(rootFolderPath, string.Empty);
|
||||||
|
using (var reader = file.OpenText())
|
||||||
|
{
|
||||||
|
while (!reader.EndOfStream)
|
||||||
|
{
|
||||||
|
var words = reader
|
||||||
|
.ReadLine()
|
||||||
|
.Split(wordSeparators, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
////.Select(f => f.Trim());
|
||||||
|
|
||||||
|
var wordIndex = 1;
|
||||||
|
foreach (var word in words)
|
||||||
|
{
|
||||||
|
if (word.Length >= MinumumWordLength)
|
||||||
|
{
|
||||||
|
index.AddWordOccurrence(word, displayFileName, file.FullName, lineNumber, wordIndex++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lineNumber++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Tests.ConsistencyTests.TextIndexing
|
||||||
|
{
|
||||||
|
public class WordIndex : Dictionary<string, WordOccurrences>
|
||||||
|
{
|
||||||
|
public WordIndex() : base(StringComparer.InvariantCultureIgnoreCase)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddWordOccurrence(string word, string fileName, string fullPath, int lineNumber, int wordIndex)
|
||||||
|
{
|
||||||
|
WordOccurrences current;
|
||||||
|
if (!this.TryGetValue(word, out current))
|
||||||
|
{
|
||||||
|
current = new WordOccurrences();
|
||||||
|
this[word] = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current.AddOccurrence(fileName, fullPath, lineNumber, wordIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WordOccurrences Find(string word)
|
||||||
|
{
|
||||||
|
WordOccurrences found;
|
||||||
|
if (this.TryGetValue(word, out found))
|
||||||
|
{
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Tests.ConsistencyTests.TextIndexing
|
||||||
|
{
|
||||||
|
public struct WordOccurrence
|
||||||
|
{
|
||||||
|
public readonly string FileName; // file containing the word.
|
||||||
|
public readonly string FullPath; // file containing the word.
|
||||||
|
public readonly int LineNumber; // line within the file.
|
||||||
|
public readonly int WordIndex; // index within the line.
|
||||||
|
|
||||||
|
public WordOccurrence(string fileName, string fullPath, int lineNumber, int wordIndex)
|
||||||
|
{
|
||||||
|
FileName = fileName;
|
||||||
|
FullPath = fullPath;
|
||||||
|
LineNumber = lineNumber;
|
||||||
|
WordIndex = wordIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Tests.ConsistencyTests.TextIndexing
|
||||||
|
{
|
||||||
|
public class WordOccurrences : List<WordOccurrence>
|
||||||
|
{
|
||||||
|
public void AddOccurrence(string fileName, string fullPath, int lineNumber, int wordIndex)
|
||||||
|
{
|
||||||
|
this.Add(new WordOccurrence(fileName, fullPath, lineNumber, wordIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<DocumentationFile>bin\Debug\MediaBrowser.Tests.XML</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.XML" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Choose>
|
<Choose>
|
||||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||||
|
@ -50,6 +52,11 @@
|
||||||
</Otherwise>
|
</Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ConsistencyTests\StringUsageReporter.cs" />
|
||||||
|
<Compile Include="ConsistencyTests\TextIndexing\IndexBuilder.cs" />
|
||||||
|
<Compile Include="ConsistencyTests\TextIndexing\WordIndex.cs" />
|
||||||
|
<Compile Include="ConsistencyTests\TextIndexing\WordOccurrence.cs" />
|
||||||
|
<Compile Include="ConsistencyTests\TextIndexing\WordOccurrences.cs" />
|
||||||
<Compile Include="MediaEncoding\Subtitles\AssParserTests.cs" />
|
<Compile Include="MediaEncoding\Subtitles\AssParserTests.cs" />
|
||||||
<Compile Include="MediaEncoding\Subtitles\SrtParserTests.cs" />
|
<Compile Include="MediaEncoding\Subtitles\SrtParserTests.cs" />
|
||||||
<Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" />
|
<Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" />
|
||||||
|
@ -98,6 +105,14 @@
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ContentWithTargetPath Include="ConsistencyTests\Resources\StringCheck.xslt">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
<TargetPath>StringCheck.xslt</TargetPath>
|
||||||
|
</ContentWithTargetPath>
|
||||||
|
<None Include="ConsistencyTests\Resources\SampleTransformed.htm" />
|
||||||
|
<None Include="ConsistencyTests\Resources\StringCheckSample.xml" />
|
||||||
|
</ItemGroup>
|
||||||
<Choose>
|
<Choose>
|
||||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user