Skip to content

Commit 5461571

Browse files
committed
Initial version of the utility
0 parents  commit 5461571

18 files changed

+763
-0
lines changed

.gitignore

+273
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Created by https://www.gitignore.io/api/aspnetcore
2+
3+
### ASPNETCore ###
4+
## Ignore Visual Studio temporary files, build results, and
5+
## files generated by popular Visual Studio add-ons.
6+
7+
# User-specific files
8+
*.suo
9+
*.user
10+
*.userosscache
11+
*.sln.docstates
12+
13+
# User-specific files (MonoDevelop/Xamarin Studio)
14+
*.userprefs
15+
16+
# Build results
17+
[Dd]ebug/
18+
[Dd]ebugPublic/
19+
[Rr]elease/
20+
[Rr]eleases/
21+
x64/
22+
x86/
23+
bld/
24+
[Bb]in/
25+
[Oo]bj/
26+
[Ll]og/
27+
28+
# Visual Studio 2015 cache/options directory
29+
.vs/
30+
# Uncomment if you have tasks that create the project's static files in wwwroot
31+
#wwwroot/
32+
33+
# MSTest test Results
34+
[Tt]est[Rr]esult*/
35+
[Bb]uild[Ll]og.*
36+
37+
# NUNIT
38+
*.VisualState.xml
39+
TestResult.xml
40+
41+
# Build Results of an ATL Project
42+
[Dd]ebugPS/
43+
[Rr]eleasePS/
44+
dlldata.c
45+
46+
# DNX
47+
project.lock.json
48+
project.fragment.lock.json
49+
artifacts/
50+
51+
*_i.c
52+
*_p.c
53+
*_i.h
54+
*.ilk
55+
*.meta
56+
*.obj
57+
*.pch
58+
*.pdb
59+
*.pgc
60+
*.pgd
61+
*.rsp
62+
*.sbr
63+
*.tlb
64+
*.tli
65+
*.tlh
66+
*.tmp
67+
*.tmp_proj
68+
*.log
69+
*.vspscc
70+
*.vssscc
71+
.builds
72+
*.pidb
73+
*.svclog
74+
*.scc
75+
76+
# Chutzpah Test files
77+
_Chutzpah*
78+
79+
# Visual C++ cache files
80+
ipch/
81+
*.aps
82+
*.ncb
83+
*.opendb
84+
*.opensdf
85+
*.sdf
86+
*.cachefile
87+
*.VC.db
88+
*.VC.VC.opendb
89+
90+
# Visual Studio profiler
91+
*.psess
92+
*.vsp
93+
*.vspx
94+
*.sap
95+
96+
# TFS 2012 Local Workspace
97+
$tf/
98+
99+
# Guidance Automation Toolkit
100+
*.gpState
101+
102+
# ReSharper is a .NET coding add-in
103+
_ReSharper*/
104+
*.[Rr]e[Ss]harper
105+
*.DotSettings.user
106+
107+
# JustCode is a .NET coding add-in
108+
.JustCode
109+
110+
# TeamCity is a build add-in
111+
_TeamCity*
112+
113+
# DotCover is a Code Coverage Tool
114+
*.dotCover
115+
116+
# Visual Studio code coverage results
117+
*.coverage
118+
*.coveragexml
119+
120+
# NCrunch
121+
_NCrunch_*
122+
.*crunch*.local.xml
123+
nCrunchTemp_*
124+
125+
# MightyMoose
126+
*.mm.*
127+
AutoTest.Net/
128+
129+
# Web workbench (sass)
130+
.sass-cache/
131+
132+
# Installshield output folder
133+
[Ee]xpress/
134+
135+
# DocProject is a documentation generator add-in
136+
DocProject/buildhelp/
137+
DocProject/Help/*.HxT
138+
DocProject/Help/*.HxC
139+
DocProject/Help/*.hhc
140+
DocProject/Help/*.hhk
141+
DocProject/Help/*.hhp
142+
DocProject/Help/Html2
143+
DocProject/Help/html
144+
145+
# Click-Once directory
146+
publish/
147+
148+
# Publish Web Output
149+
*.[Pp]ublish.xml
150+
*.azurePubxml
151+
# TODO: Comment the next line if you want to checkin your web deploy settings
152+
# but database connection strings (with potential passwords) will be unencrypted
153+
*.pubxml
154+
*.publishproj
155+
156+
# Microsoft Azure Web App publish settings. Comment the next line if you want to
157+
# checkin your Azure Web App publish settings, but sensitive information contained
158+
# in these scripts will be unencrypted
159+
PublishScripts/
160+
161+
# NuGet Packages
162+
*.nupkg
163+
# The packages folder can be ignored because of Package Restore
164+
**/packages/*
165+
# except build/, which is used as an MSBuild target.
166+
!**/packages/build/
167+
# Uncomment if necessary however generally it will be regenerated when needed
168+
#!**/packages/repositories.config
169+
# NuGet v3's project.json files produces more ignoreable files
170+
*.nuget.props
171+
*.nuget.targets
172+
173+
# Microsoft Azure Build Output
174+
csx/
175+
*.build.csdef
176+
177+
# Microsoft Azure Emulator
178+
ecf/
179+
rcf/
180+
181+
# Windows Store app package directories and files
182+
AppPackages/
183+
BundleArtifacts/
184+
Package.StoreAssociation.xml
185+
_pkginfo.txt
186+
187+
# Visual Studio cache files
188+
# files ending in .cache can be ignored
189+
*.[Cc]ache
190+
# but keep track of directories ending in .cache
191+
!*.[Cc]ache/
192+
193+
# Others
194+
ClientBin/
195+
~$*
196+
*~
197+
*.dbmdl
198+
*.dbproj.schemaview
199+
*.jfm
200+
*.pfx
201+
*.publishsettings
202+
node_modules/
203+
orleans.codegen.cs
204+
205+
# Since there are multiple workflows, uncomment next line to ignore bower_components
206+
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
207+
#bower_components/
208+
209+
# RIA/Silverlight projects
210+
Generated_Code/
211+
212+
# Backup & report files from converting an old project file
213+
# to a newer Visual Studio version. Backup files are not needed,
214+
# because we have git ;-)
215+
_UpgradeReport_Files/
216+
Backup*/
217+
UpgradeLog*.XML
218+
UpgradeLog*.htm
219+
220+
# SQL Server files
221+
*.mdf
222+
*.ldf
223+
224+
# Business Intelligence projects
225+
*.rdl.data
226+
*.bim.layout
227+
*.bim_*.settings
228+
229+
# Microsoft Fakes
230+
FakesAssemblies/
231+
232+
# GhostDoc plugin setting file
233+
*.GhostDoc.xml
234+
235+
# Node.js Tools for Visual Studio
236+
.ntvs_analysis.dat
237+
238+
# Visual Studio 6 build log
239+
*.plg
240+
241+
# Visual Studio 6 workspace options file
242+
*.opt
243+
244+
# Visual Studio LightSwitch build output
245+
**/*.HTMLClient/GeneratedArtifacts
246+
**/*.DesktopClient/GeneratedArtifacts
247+
**/*.DesktopClient/ModelManifest.xml
248+
**/*.Server/GeneratedArtifacts
249+
**/*.Server/ModelManifest.xml
250+
_Pvt_Extensions
251+
252+
# Paket dependency manager
253+
.paket/paket.exe
254+
paket-files/
255+
256+
# FAKE - F# Make
257+
.fake/
258+
259+
# JetBrains Rider
260+
.idea/
261+
*.sln.iml
262+
263+
# CodeRush
264+
.cr/
265+
266+
# Python Tools for Visual Studio (PTVS)
267+
__pycache__/
268+
*.pyc
269+
270+
# Cake - Uncomment if you are using it
271+
# tools/
272+
273+
# End of https://www.gitignore.io/api/aspnetcore

PoExtractor.sln

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio 15
4+
VisualStudioVersion = 15.0.27004.2009
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PoExtractor", "PoExtractor\PoExtractor.csproj", "{A29A064D-8EB5-4D0F-A78C-2C6021340A17}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{A29A064D-8EB5-4D0F-A78C-2C6021340A17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{A29A064D-8EB5-4D0F-A78C-2C6021340A17}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{A29A064D-8EB5-4D0F-A78C-2C6021340A17}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{A29A064D-8EB5-4D0F-A78C-2C6021340A17}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {694D0244-80FF-47D4-A54D-2DB1356B72A1}
24+
EndGlobalSection
25+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Microsoft.CodeAnalysis;
2+
3+
namespace PoExtractor.Core.Extractors {
4+
public abstract class LocalizableStringExtractor : ILocalizableStringExtractor {
5+
public ILocalizableMetadataProvider MetadataProvider { get; private set; }
6+
7+
public LocalizableStringExtractor(ILocalizableMetadataProvider metadataProvider) {
8+
this.MetadataProvider = metadataProvider;
9+
}
10+
11+
public abstract LocalizableStringOccurence TryExtract(SyntaxNode node);
12+
13+
protected LocalizableStringOccurence CreateLocalizedString(string text, string textPlural, SyntaxNode node) {
14+
var result = new LocalizableStringOccurence() {
15+
Text = text,
16+
TextPlural = textPlural,
17+
Location = this.MetadataProvider.GetLocation(node),
18+
Context = this.MetadataProvider.GetContext(node)
19+
};
20+
21+
return result;
22+
}
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
5+
namespace PoExtractor.Core.Extractors {
6+
public class PluralStringExtractor : LocalizableStringExtractor {
7+
public PluralStringExtractor(ILocalizableMetadataProvider metadataProvider) : base(metadataProvider) {
8+
}
9+
10+
public override LocalizableStringOccurence TryExtract(SyntaxNode node) {
11+
if (node is InvocationExpressionSyntax invocation &&
12+
invocation.Expression is MemberAccessExpressionSyntax accessor &&
13+
accessor.Expression is IdentifierNameSyntax identifierName &&
14+
identifierName.Identifier.Text == "T" &&
15+
accessor.Name.Identifier.Text == "Plural") {
16+
17+
var arguments = invocation.ArgumentList.Arguments;
18+
if (arguments.Count >= 2 &&
19+
arguments[1].Expression is ArrayCreationExpressionSyntax array) {
20+
if (array.Type.ElementType is PredefinedTypeSyntax arrayType &&
21+
arrayType.Keyword.Text == "string" &&
22+
array.Initializer.Expressions.Count >= 2 &&
23+
array.Initializer.Expressions[0] is LiteralExpressionSyntax singularLiteral && singularLiteral.IsKind(SyntaxKind.StringLiteralExpression) &&
24+
array.Initializer.Expressions[1] is LiteralExpressionSyntax pluralLiteral && pluralLiteral.IsKind(SyntaxKind.StringLiteralExpression)) {
25+
26+
return this.CreateLocalizedString(singularLiteral.Token.ValueText, pluralLiteral.Token.ValueText, node);
27+
}
28+
} else {
29+
if (arguments.Count >= 3 &&
30+
arguments[1].Expression is LiteralExpressionSyntax singularLiteral && singularLiteral.IsKind(SyntaxKind.StringLiteralExpression) &&
31+
arguments[2].Expression is LiteralExpressionSyntax pluralLiteral && pluralLiteral.IsKind(SyntaxKind.StringLiteralExpression)) {
32+
33+
return this.CreateLocalizedString(singularLiteral.Token.ValueText, pluralLiteral.Token.ValueText, node);
34+
}
35+
}
36+
}
37+
38+
return null;
39+
}
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
5+
namespace PoExtractor.Core.Extractors {
6+
public class SingularStringExtractor : LocalizableStringExtractor {
7+
public SingularStringExtractor(ILocalizableMetadataProvider metadataProvider) : base(metadataProvider) {
8+
}
9+
10+
public override LocalizableStringOccurence TryExtract(SyntaxNode node) {
11+
if (node is ElementAccessExpressionSyntax accessor &&
12+
accessor.Expression is IdentifierNameSyntax identifierName &&
13+
identifierName.Identifier.Text == "T" &&
14+
accessor.ArgumentList != null) {
15+
16+
var argument = accessor.ArgumentList.Arguments.FirstOrDefault();
17+
if (argument != null && argument.Expression is LiteralExpressionSyntax literal && literal.IsKind(SyntaxKind.StringLiteralExpression)) {
18+
19+
return this.CreateLocalizedString(literal.Token.ValueText, null, node);
20+
}
21+
}
22+
23+
return null;
24+
}
25+
}
26+
}

0 commit comments

Comments
 (0)