├── .gitattributes
├── .gitignore
├── LICENSE
├── Localization.sln
├── README.md
└── src
├── Attributes
├── CompareLocalizeAttribute.cs
├── DescriptionLocalizeAttribute.cs
├── DisplayLocalizeAttribute.cs
├── RequiredLocalizeAttribute.cs
└── StringLengthAttribute.cs
├── GetPropertyValue.cs
├── Helpers
├── ActionLinkLocalization.cs
├── ActionLocalization.cs
└── LocalizeHelpers.cs
├── Inline.cs
├── Inline.tt
├── Localization.cs
├── Localization.csproj
├── LocalizationStartup.cs
├── Properties
├── Annotations.cs
└── AssemblyInfo.cs
└── Resource.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 | Extras/
18 |
19 | .vs/*
20 |
21 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
22 | !packages/*/build/
23 |
24 | # MSTest test Results
25 | [Tt]est[Rr]esult*/
26 | [Bb]uild[Ll]og.*
27 | UnitTestResults.html
28 |
29 | *_i.c
30 | *_p.c
31 | *.ilk
32 | *.meta
33 | *.obj
34 | *.pch
35 | *.pdb
36 | *.pgc
37 | *.pgd
38 | *.rsp
39 | *.sbr
40 | *.tlb
41 | *.tli
42 | *.tlh
43 | *.tmp
44 | *.tmp_proj
45 | *.log
46 | *.vspscc
47 | *.vssscc
48 | .builds
49 | *.pidb
50 | *.log
51 | *.scc
52 |
53 | # Visual Studio cache files
54 | *.sln.ide/
55 |
56 | # Visual C++ cache files
57 | ipch/
58 | *.aps
59 | *.ncb
60 | *.opensdf
61 | *.sdf
62 | *.cachefile
63 |
64 | # Visual Studio profiler
65 | *.psess
66 | *.vsp
67 | *.vspx
68 |
69 | # Guidance Automation Toolkit
70 | *.gpState
71 |
72 | # ReSharper is a .NET coding add-in
73 | _ReSharper*/
74 | *.[Rr]e[Ss]harper
75 |
76 | # TeamCity is a build add-in
77 | _TeamCity*
78 |
79 | # DotCover is a Code Coverage Tool
80 | *.dotCover
81 |
82 | # NCrunch
83 | *.ncrunch*
84 | .*crunch*.local.xml
85 |
86 | # Installshield output folder
87 | [Ee]xpress/
88 |
89 | # DocProject is a documentation generator add-in
90 | DocProject/buildhelp/
91 | DocProject/Help/*.HxT
92 | DocProject/Help/*.HxC
93 | DocProject/Help/*.hhc
94 | DocProject/Help/*.hhk
95 | DocProject/Help/*.hhp
96 | DocProject/Help/Html2
97 | DocProject/Help/html
98 |
99 | # Click-Once directory
100 | publish/
101 |
102 | # Publish Web Output
103 | *.Publish.xml
104 |
105 | # NuGet Packages Directory
106 | packages/
107 |
108 | # Windows Azure Build Output
109 | csx
110 | *.build.csdef
111 |
112 | # Windows Store app package directory
113 | AppPackages/
114 |
115 | # Others
116 | sql/
117 | *.Cache
118 | ClientBin/
119 | [Ss]tyle[Cc]op.*
120 | ~$*
121 | *~
122 | *.dbmdl
123 | *.[Pp]ublish.xml
124 | *.pfx
125 | *.publishsettings
126 |
127 | # RIA/Silverlight projects
128 | Generated_Code/
129 |
130 | # Backup & report files from converting an old project file to a newer
131 | # Visual Studio version. Backup files are not needed, because we have git ;-)
132 | _UpgradeReport_Files/
133 | Backup*/
134 | UpgradeLog*.XML
135 | UpgradeLog*.htm
136 |
137 | # SQL Server files
138 | App_Data/*.mdf
139 | App_Data/*.ldf
140 |
141 |
142 | #LightSwitch generated files
143 | GeneratedArtifacts/
144 | _Pvt_Extensions/
145 | ModelManifest.xml
146 |
147 | # =========================
148 | # Windows detritus
149 | # =========================
150 |
151 | # Windows image file caches
152 | Thumbs.db
153 | ehthumbs.db
154 |
155 | # Folder config file
156 | Desktop.ini
157 |
158 | # Recycle Bin used on file shares
159 | $RECYCLE.BIN/
160 |
161 | # Mac desktop service store files
162 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Yasin Kuyu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Localization.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.30501.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Localization", "src\Localization.csproj", "{44EFDC86-75C7-4928-A03E-153E29755ACD}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C19889E3-9AFA-4EC2-A0E0-6DBB0885DB3E}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{16FE18CA-BBCD-4F5F-A241-3A575FA711D9}"
11 | ProjectSection(SolutionItems) = preProject
12 | .gitignore = .gitignore
13 | README.md = README.md
14 | EndProjectSection
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {44EFDC86-75C7-4928-A03E-153E29755ACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {44EFDC86-75C7-4928-A03E-153E29755ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {44EFDC86-75C7-4928-A03E-153E29755ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {44EFDC86-75C7-4928-A03E-153E29755ACD}.Release|Any CPU.Build.0 = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | GlobalSection(NestedProjects) = preSolution
31 | {44EFDC86-75C7-4928-A03E-153E29755ACD} = {C19889E3-9AFA-4EC2-A0E0-6DBB0885DB3E}
32 | EndGlobalSection
33 | EndGlobal
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Localization
2 | ============
3 |
4 | Create `multi-language` structure with ASP.NET MVC [@yasinkuyu](https://twitter.com/yasinkuyu)
5 |
6 | PM> Install-Package Localization
7 |
8 |
9 | ### Usage
10 |
11 | -
@Html.ActionLinkLocalization("English", "Index", "Locales", new { lang = "en_US" })
12 | - @Html.ActionLinkLocalization("Türkçe", "Index", "Locales", new { lang = "tr_TR" })
13 | and more...
14 | Or
15 | - English
16 | - Türkçe
17 | and more...
18 |
19 | Index.cshtml
20 |
21 | @Html.Get("homepage") or @Html.Localize("homepage")
22 |
23 |
24 | ### Video Tutorial
25 |
26 |
27 |
28 | [](https://vimeo.com/96483908)
29 |
30 |
31 | [](http://youtu.be/9V5PS4m0er0)
32 |
33 |
34 |
35 | Requirements
36 | ---------------
37 |
38 | Localization
39 | - en_US.xml
40 | - tr_TR.xml
41 | - and more...
42 |
43 | Bin
44 | - Insya.Localization.dll
45 | - System.ComponentModel.DataAnnotations
46 |
47 |
48 |
49 | Default locale
50 |
51 | public void DefaultLocale( )
52 | {
53 | HttpCookie cookie = Request.Cookies.Get("CacheLang");
54 | if ( cookie == null)
55 | {
56 | HttpCookie newCookie = new HttpCookie("CacheLang");
57 | newCookie.Value = "en_US";
58 | Response.Cookies.Add(newCookie);
59 | }
60 | }
61 |
62 |
63 | Structure
64 | ---------------
65 |
66 | ### Views
67 | Xml file
68 | - Home Page
69 |
70 | Razor
71 | @Html.Localize("homepage")
72 | Or
73 | @Html.Get("homepage")
74 |
75 | Code Behind
76 | Localization.Localize("homepage")
77 | Or
78 | Localization.Get("homepage")
79 |
80 | @Html.ActionLinkLocalization()
81 | @Html.ActionLocalization()
82 |
83 |
84 | ### Inline Localization
85 |
86 | @Html.Get(new Inline(en: "book", tr: "kitap"))
87 | @Html.Localize(new Inline(en: "book", tr: "kitap"))
88 |
89 |
90 |
91 |
92 |
93 | ### Controllers
94 |
95 | ```
96 | public ActionResult Index(string lang = "en_US")
97 | {
98 | Response.Cookies["CacheLang"].Value = lang;
99 |
100 | if (Request.UrlReferrer != null)
101 | Response.Redirect(Request.UrlReferrer.ToString());
102 |
103 | var message = Localization.Get("changedlng");
104 |
105 | return Content(message);
106 | }
107 | ```
108 |
109 | ### Models
110 |
111 | Attribute Localize
112 | Display Attribute
113 | [DisplayLocalize("username")]
114 | public string Username { get; set; }
115 |
116 | String Length Attribute
117 | [StringLengthLocalize(20, MinimumLength = 4)]
118 | public string DisplayName { get; set; }
119 |
120 | Required Attribute
121 | [RequiredLocalized]
122 | public string DisplayName { get; set; }
123 |
124 | Description Attribute
125 | [DescriptionLocalize]
126 | public string DisplayName { get; set; }
127 |
128 | ----------
129 |
130 | **Intellisense in razor files (Views/web.config)**
131 | - Views
132 | - web.config
133 | - system.web.webPages.razor
134 | - pages
135 | - namespaces
136 | - add namespace="Insya.Localization"
137 | - add namespace="Insya.Localization.Helpers"
138 |
139 |
140 | Example
141 |
142 | ```
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | ##
153 | ##
154 |
155 |
156 |
157 | ```
158 |
159 | **Note:** Nuget package auto insert
160 |
161 | ### Language Codes
162 |
163 | https://msdn.microsoft.com/en-us/library/ms533052(v=vs.85).aspx
164 |
165 | ### Contribution
166 | Fork
167 |
168 |
169 | **Roadmap:**
170 | - Localizable Routing
171 | - All the XML language files editing tool on one screen.
172 | - Testing tools
173 |
--------------------------------------------------------------------------------
/src/Attributes/CompareLocalizeAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel.DataAnnotations;
3 | using System.Globalization;
4 |
5 | namespace Insya.Localization.Attributes {
6 |
7 | ///
8 | /// Localized .
9 | ///
10 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
11 | public sealed class CompareLocalizeAttribute : CompareAttribute
12 | {
13 | ///
14 | /// The text id.
15 | ///
16 | private string Id { get; set; }
17 |
18 | #region Initialization
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | /// The property to compare with the current property.
24 | public CompareLocalizeAttribute(string otherProperty) : this(otherProperty, "compare")
25 | {
26 | }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | /// The property to compare with the current property.
32 | /// The text id.
33 | public CompareLocalizeAttribute(string otherProperty, string id) : base(otherProperty)
34 | {
35 | Id = id;
36 | }
37 | #endregion Initialization
38 |
39 | #region Overrides
40 | ///
41 | /// Applies formatting to an error message, based on the data field where the error occurred.
42 | ///
43 | /// The name of the field that caused the validation failure.
44 | ///
45 | /// The formatted error message.
46 | ///
47 | public override string FormatErrorMessage(string name)
48 | {
49 | return string.Format(CultureInfo.CurrentCulture, Localization.Localize(Id), name, OtherPropertyDisplayName ?? OtherProperty);
50 | }
51 | #endregion Overrides
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/Attributes/DescriptionLocalizeAttribute.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System;
5 | using System.ComponentModel;
6 |
7 | namespace Insya.Localization.Attributes
8 | {
9 | ///
10 | /// Localized .
11 | ///
12 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
13 | public sealed class DescriptionLocalizeAttribute : DescriptionAttribute
14 | {
15 | #region Initialization
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The text id.
20 | public DescriptionLocalizeAttribute(string id) : base(id)
21 | {
22 | }
23 | #endregion Initialization
24 |
25 | #region Overrides
26 | ///
27 | /// Gets the description stored in this attribute.
28 | ///
29 | ///
30 | ///
31 | /// The description stored in this attribute.
32 | ///
33 | public override string Description
34 | {
35 | get
36 | {
37 | return Localization.Localize(base.Description) ?? base.Description;
38 | }
39 | }
40 | #endregion Overrides
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Attributes/DisplayLocalizeAttribute.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System;
5 | using System.ComponentModel;
6 |
7 | namespace Insya.Localization.Attributes
8 | {
9 | ///
10 | /// Localized .
11 | ///
12 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)]
13 | public sealed class DisplayLocalizeAttribute : DisplayNameAttribute
14 | {
15 | #region Initialization
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The text id.
20 | public DisplayLocalizeAttribute(string id) : base(id)
21 | {
22 | }
23 | #endregion Initialization
24 |
25 | #region Overrides
26 | ///
27 | /// Gets the display name for a property, event, or public void method that takes no arguments stored in this attribute.
28 | ///
29 | ///
30 | ///
31 | /// The display name.
32 | ///
33 | public override string DisplayName
34 | {
35 | get
36 | {
37 | return Localization.Localize(base.DisplayName) ?? base.DisplayName;
38 | }
39 | }
40 | #endregion Overrides
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/Attributes/RequiredLocalizeAttribute.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System;
5 | using System.ComponentModel.DataAnnotations;
6 | using System.Globalization;
7 |
8 | namespace Insya.Localization.Attributes
9 | {
10 | ///
11 | /// Localized .
12 | ///
13 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
14 | public class RequiredLocalizedAttribute : RequiredAttribute
15 | {
16 | ///
17 | /// The text id.
18 | ///
19 | private string Id { get; set; }
20 |
21 | #region Initialization
22 | ///
23 | /// Initializes a new instance of the class.
24 | ///
25 | public RequiredLocalizedAttribute() : this("required")
26 | {
27 | }
28 |
29 | ///
30 | /// Initializes a new instance of the class.
31 | ///
32 | /// The text id.
33 | public RequiredLocalizedAttribute(string id)
34 | {
35 | Id = id;
36 | }
37 | #endregion Initialization
38 |
39 | #region Overrides
40 | ///
41 | /// Applies formatting to an error message, based on the data field where the error occurred.
42 | ///
43 | /// The name to include in the formatted message.
44 | /// An instance of the formatted error message.
45 | public override string FormatErrorMessage(string name)
46 | {
47 | return string.Format(CultureInfo.CurrentCulture, Localization.Localize(Id), name);
48 | }
49 | #endregion Overrides
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Attributes/StringLengthAttribute.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System;
5 | using System.ComponentModel.DataAnnotations;
6 | using System.Globalization;
7 |
8 | namespace Insya.Localization.Attributes
9 | {
10 | ///
11 | /// Localized .
12 | ///
13 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
14 | public sealed class StringLengthLocalizeAttribute : ValidationAttribute
15 | {
16 | ///
17 | /// The allowed string maximum length.
18 | ///
19 | public int MaximumLength
20 | {
21 | get;
22 | private set;
23 | }
24 |
25 | ///
26 | /// The allowed string minimum length.
27 | ///
28 | public int MinimumLength
29 | {
30 | get;
31 | private set;
32 | }
33 |
34 | #region Initialization
35 | ///
36 | /// Initializes a new instance of the class.
37 | ///
38 | /// The allowed string maximum length.
39 | public StringLengthLocalizeAttribute(int maximumLength) : this("stringLength", maximumLength)
40 | {
41 | }
42 |
43 | ///
44 | /// Initializes a new instance of the class.
45 | ///
46 | /// The text id.
47 | /// The allowed string maximum length.
48 | public StringLengthLocalizeAttribute(string id, int maximumLength) : this(id, maximumLength, 0)
49 | {
50 | }
51 |
52 | ///
53 | /// Initializes a new instance of the class.
54 | ///
55 | /// The allowed string minimum length.
56 | /// The allowed string maximum length.
57 | public StringLengthLocalizeAttribute(int maximumLength, int minimumLength) : this("stringLength", maximumLength, minimumLength)
58 | {
59 | }
60 |
61 | ///
62 | /// Initializes a new instance of the class.
63 | ///
64 | /// The text id.
65 | /// The allowed string minimum length.
66 | /// The allowed string maximum length.
67 | public StringLengthLocalizeAttribute(string id, int maximumLength, int minimumLength) : base(new Func(() => Localization.Localize(id)))
68 | {
69 | MaximumLength = maximumLength;
70 | MinimumLength = minimumLength;
71 | }
72 | #endregion Initialization
73 |
74 | #region Overrides
75 | ///
76 | /// Applies formatting to an error message, based on the data field where the error occurred.
77 | ///
78 | /// The name to include in the formatted message.
79 | /// An instance of the formatted error message.
80 | public override string FormatErrorMessage(string name)
81 | {
82 | return string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, MaximumLength, MinimumLength);
83 | }
84 |
85 | ///
86 | /// Determines whether the specified value of the object is valid.
87 | ///
88 | /// The value of the object to validate.
89 | /// true if the specified value is valid; otherwise, false.
90 | public override bool IsValid(object value)
91 | {
92 | if (value == null)
93 | {
94 | return true;
95 | }
96 | string text = (string)value;
97 | if (MaximumLength < 0)
98 | {
99 | throw new InvalidOperationException("The maximum length must be a nonnegative integer.");
100 | }
101 | if (MinimumLength > MaximumLength)
102 | {
103 | throw new InvalidOperationException(string.Format("The maximum value '{0}' must be greater than or equal to the minimum value '{1}'.", MaximumLength, MinimumLength));
104 | }
105 | int length = text.Length;
106 | return length <= MaximumLength && length >= MinimumLength;
107 | }
108 | #endregion Overrides
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/GetPropertyValue.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 |
3 | namespace Insya.Localization
4 | {
5 | public class GetPropertyByValue
6 | {
7 |
8 | ///
9 | /// Get Property Value by name
10 | ///
11 | ///
12 | ///
13 | ///
14 | public object GetValue(object car, string propertyName)
15 | {
16 | return car.GetType().GetProperties()
17 | .Single(pi => pi.Name.Replace("@", "") == propertyName)
18 | .GetValue(car, null);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Helpers/ActionLinkLocalization.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System.Web.Mvc;
5 | using System.Web.Routing;
6 |
7 | namespace Insya.Localization.Helpers
8 | {
9 | public static partial class HtmlHelperExtensions
10 | {
11 |
12 | ///
13 | /// MVC Action link localization html helper
14 | /// Example @Html.ActionLinkLocalization("homepage", "Index", "Home") -> - Home Page
15 | /// Output :
16 | ///
17 | ///
18 | ///
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | public static MvcHtmlString ActionLinkLocalization(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues = null, object htmlAttributes = null)
25 | {
26 | var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
27 | var tagBuilder = new TagBuilder("a") { InnerHtml = Localization.Localize(linkText) };
28 |
29 | tagBuilder.Attributes["href"] = urlHelper.Action(actionName.ToLowerInvariant(), controllerName.ToLowerInvariant(), routeValues);
30 |
31 | tagBuilder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
32 |
33 | return MvcHtmlString.Create(tagBuilder.ToString());
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Helpers/ActionLocalization.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System.Web.Mvc;
5 |
6 | namespace Insya.Localization.Helpers
7 | {
8 | public static partial class HtmlHelperExtensions
9 | {
10 |
11 | ///
12 | /// MVC Action link localization url helper
13 | /// Example @Html.ActionLocalization("homepage", "Index", "Home") -> - Home Page
14 | /// Output : /Homepage/
15 | ///
16 | ///
17 | ///
18 | ///
19 | ///
20 | ///
21 | public static string ActionLocalization(this UrlHelper urlHelper, string actionName, string controllerName, object routeValues = null)
22 | {
23 | var scheme = urlHelper.RequestContext.HttpContext.Request.Url.Scheme;
24 |
25 | return urlHelper.Action(actionName, controllerName, routeValues, scheme);
26 | }
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Helpers/LocalizeHelpers.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System.Web.Mvc;
5 |
6 | namespace Insya.Localization.Helpers
7 | {
8 |
9 | public static partial class HtmlHelperExtensions
10 | {
11 | ///
12 | /// Razor template using @Html.Localize("id")
13 | ///
14 | ///
15 | ///
16 | ///
17 | public static MvcHtmlString Localize(this HtmlHelper helper, string id)
18 | {
19 | return new MvcHtmlString(Localization.Localize(id));
20 | }
21 |
22 | ///
23 | /// Razor template using @Html.Localize("id")
24 | ///
25 | ///
26 | ///
27 | ///
28 | public static MvcHtmlString Localize(this HtmlHelper helper, Inline lang)
29 | {
30 | return new MvcHtmlString(Localization.Localize(lang));
31 | }
32 |
33 | ///
34 | /// or Razor template using @Html.Loc("id")
35 | ///
36 | ///
37 | ///
38 | ///
39 | public static MvcHtmlString Loc(this HtmlHelper helper, string id)
40 | {
41 | return new MvcHtmlString(Localization.Localize(id));
42 | }
43 |
44 | ///
45 | /// or Razor template using @Html.Loc("id")
46 | ///
47 | ///
48 | ///
49 | ///
50 | public static MvcHtmlString Get(this HtmlHelper helper, string id)
51 | {
52 | return new MvcHtmlString(Localization.Localize(id));
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/Inline.tt:
--------------------------------------------------------------------------------
1 | <#@ template debug="true" hostSpecific="true" #>
2 | <#@ output extension=".cs" #>
3 | <#@ Assembly Name="System" #>
4 | <#@ Assembly Name="System.Core" #>
5 | <#@ import namespace="System.Globalization" #>
6 | <#@ import namespace="System.Collections.Generic" #>
7 | <#@ import namespace="System.Linq" #>
8 | <#@ import namespace="Microsoft.CSharp" #>
9 | <#
10 | List localeList = new List();
11 | #>
12 | namespace Insya.Localization
13 | {
14 | public partial class Inline {
15 |
16 | <# foreach(CultureInfo cultureInfo in CultureInfo.GetCultures(CultureTypes.AllCultures).Where(c => !string.IsNullOrEmpty(c.Name))) { #>
17 | <#
18 | string locale = cultureInfo.Name.Replace("-", "_");
19 |
20 | CSharpCodeProvider cs = new CSharpCodeProvider();
21 |
22 | if (!cs.IsValidIdentifier(locale)) {
23 | locale = string.Format("@{0}", locale);
24 | }
25 |
26 | localeList.Add(locale);
27 | #>
28 | ///
29 | /// <#= cultureInfo.DisplayName #>
30 | ///
31 | ///
32 | public string <#= locale #> { get; set; }
33 |
34 | <# } #>
35 | public Inline(<#= string.Join(", ", localeList.Select(l => string.Format("string {0} = \"\"", l)).ToArray()) #>)
36 | {
37 | <# foreach(string locale in localeList) { #>
38 | <#= string.Format("this.{0} = {1};", locale, locale) #>
39 | <# } #>
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/Localization.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | namespace Insya.Localization
5 | {
6 | public static class Localization
7 | {
8 | private static LocalizationStartup _loc;
9 |
10 | static Localization()
11 | {
12 | _loc = new LocalizationStartup();
13 | }
14 |
15 | ///
16 | /// Alternative calling Localize("id") or Get("id")
17 | ///
18 | ///
19 | ///
20 | public static string Get(string id)
21 | {
22 | return _loc.GetLang(id);
23 | }
24 |
25 | ///
26 | /// Example - Home Page
27 | ///
28 | ///
29 | /// xml item id
30 | /// xml culture name
31 | public static string Get(string id, string culture)
32 | {
33 | return _loc.GetLang(id, culture);
34 | }
35 |
36 | ///
37 | /// Inline localization
38 | ///
39 | ///
40 | public static string Get(Inline lang)
41 | {
42 | return _loc.GetLang(lang);
43 | }
44 |
45 | ///
46 | /// Example - Home Page
47 | ///
48 | ///
49 | /// xml item id
50 | public static string Localize(string id)
51 | {
52 | return _loc.GetLang(id);
53 | }
54 |
55 | ///
56 | /// Example - Home Page
57 | ///
58 | ///
59 | /// xml item id
60 | /// xml culture name
61 | public static string Localize(string id, string culture)
62 | {
63 | return _loc.GetLang(id, culture);
64 | }
65 |
66 | ///
67 | /// Inline localization
68 | ///
69 | ///
70 | public static string Localize(Inline lang)
71 | {
72 | return _loc.GetLang(lang);
73 | }
74 |
75 |
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/Localization.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {44EFDC86-75C7-4928-A03E-153E29755ACD}
8 | Library
9 | Properties
10 | Insya.Localization
11 | Insya.Localization
12 | v4.0
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
73 |
--------------------------------------------------------------------------------
/src/LocalizationStartup.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System.Globalization;
5 | using System.Web;
6 |
7 | namespace Insya.Localization
8 | {
9 | internal class LocalizationStartup
10 | {
11 | private const string CacheLangCookieName = "CacheLang";
12 |
13 | private static string defaultCulture;
14 |
15 | private static string DefaultCulture {
16 | get
17 | {
18 | if (string.IsNullOrEmpty(defaultCulture)) {
19 | // https://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx
20 | defaultCulture = new CultureInfo("en-US").Name;
21 | }
22 |
23 | return defaultCulture;
24 | }
25 | }
26 |
27 | ///
28 | /// Localization Culture (ex: tr-TR)
29 | ///
30 | ///
31 | private string Culture { get; set; }
32 |
33 | /// Unique applization id (* optional)
34 | private string AppName { get; set; }
35 |
36 | ///
37 | /// Custom Xml folder id (* optional) (Default folder name Localization)
38 | ///
39 | ///
40 | private string Folder { get; set; }
41 |
42 | public bool ReadCookie()
43 | {
44 | if (HttpContext.Current == null) {
45 | return false;
46 | }
47 |
48 | Culture = string.Format("{0}", DefaultCulture);
49 |
50 | var cookieLanguage = HttpContext.Current.Request.Cookies[CacheLangCookieName];
51 |
52 | if (cookieLanguage != null)
53 | {
54 | Culture = string.Format("{0}", cookieLanguage.Value);
55 | }
56 | else
57 | {
58 | var httpCookie = HttpContext.Current.Response.Cookies[CacheLangCookieName];
59 | if (httpCookie != null)
60 | httpCookie.Value = DefaultCulture;
61 |
62 | if (cookieLanguage != null)
63 | Culture = string.Format("{0}", cookieLanguage.Value);
64 |
65 | }
66 |
67 | return true;
68 | }
69 |
70 | ///
71 | /// Xml localization item id usgin GetLang("itemName")
72 | ///
73 | /// Xml localization item id
74 | ///
75 | public string GetLang(string id, string _culture = "")
76 | {
77 | if (!ReadCookie()) {
78 | return id;
79 | }
80 |
81 | // Unique applization default id
82 | string uniqueApplicationName = "InsyaLocalization";
83 | string xmlFolderName = "Localization";
84 |
85 | // If used more than once on a server, enter a unique id for each project.
86 | if (string.IsNullOrEmpty(AppName))
87 | AppName = uniqueApplicationName;
88 |
89 | if (string.IsNullOrEmpty(Folder))
90 | Folder = xmlFolderName;
91 |
92 | if (!string.IsNullOrEmpty(_culture))
93 | Culture = _culture;
94 |
95 | string applicationName = string.Format("{0}_{1}_", Culture, uniqueApplicationName);
96 |
97 | string key = applicationName + id;
98 |
99 | if (HttpContext.Current.Application[key] == null)
100 | {
101 | string path = HttpContext.Current.Server.MapPath(string.Format("~/{0}/{1}.xml", xmlFolderName, Culture));
102 |
103 | Resource.GetXmlResource(path, applicationName);
104 | }
105 |
106 | object valueObj = HttpContext.Current.Application[key];
107 | if (valueObj == null)
108 | return id;
109 | else return valueObj.ToString();
110 | }
111 |
112 | ///
113 | /// Xml localization item id usgin GetLang("itemName")
114 | ///
115 | ///
116 | ///
117 | public string GetLang(Inline lang)
118 | {
119 | if (!ReadCookie()) {
120 | return DefaultCulture;
121 | }
122 |
123 | if (Culture != null)
124 | {
125 | var propy = new GetPropertyByValue();
126 | var value = (string)propy.GetValue(lang, Culture);
127 |
128 | return value;
129 | }
130 |
131 | return DefaultCulture;
132 | }
133 |
134 | // ToDo this
135 | public string SetLang(string lang)
136 | {
137 | var cookieLanguage = HttpContext.Current.Request.Cookies[CacheLangCookieName];
138 |
139 | if (cookieLanguage != null)
140 | {
141 | var cookie = string.Format("{0}", cookieLanguage.Value);
142 | }
143 |
144 | return null;
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/Properties/Annotations.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | #pragma warning disable 1591
4 | // ReSharper disable UnusedMember.Global
5 | // ReSharper disable UnusedParameter.Local
6 | // ReSharper disable MemberCanBePrivate.Global
7 | // ReSharper disable UnusedAutoPropertyAccessor.Global
8 | // ReSharper disable IntroduceOptionalParameters.Global
9 | // ReSharper disable MemberCanBeProtected.Global
10 | // ReSharper disable InconsistentNaming
11 |
12 | namespace Insya.Localization.Annotations
13 | {
14 | ///
15 | /// Indicates that the value of the marked element could be null sometimes,
16 | /// so the check for null is necessary before its usage
17 | ///
18 | ///
19 | /// [CanBeNull] public object Test() { return null; }
20 | /// public void UseTest() {
21 | /// var p = Test();
22 | /// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
23 | /// }
24 | ///
25 | [AttributeUsage(
26 | AttributeTargets.Method | AttributeTargets.Parameter |
27 | AttributeTargets.Property | AttributeTargets.Delegate |
28 | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
29 | public sealed class CanBeNullAttribute : Attribute { }
30 |
31 | ///
32 | /// Indicates that the value of the marked element could never be null
33 | ///
34 | ///
35 | /// [NotNull] public object Foo() {
36 | /// return null; // Warning: Possible 'null' assignment
37 | /// }
38 | ///
39 | [AttributeUsage(
40 | AttributeTargets.Method | AttributeTargets.Parameter |
41 | AttributeTargets.Property | AttributeTargets.Delegate |
42 | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
43 | public sealed class NotNullAttribute : Attribute { }
44 |
45 | ///
46 | /// Indicates that the marked method builds string by format pattern and (optional) arguments.
47 | /// Parameter, which contains format string, should be given in constructor. The format string
48 | /// should be in -like form
49 | ///
50 | ///
51 | /// [StringFormatMethod("message")]
52 | /// public void ShowError(string message, params object[] args) { /* do something */ }
53 | /// public void Foo() {
54 | /// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
55 | /// }
56 | ///
57 | [AttributeUsage(
58 | AttributeTargets.Constructor | AttributeTargets.Method,
59 | AllowMultiple = false, Inherited = true)]
60 | public sealed class StringFormatMethodAttribute : Attribute
61 | {
62 | ///
63 | /// Specifies which parameter of an annotated method should be treated as format-string
64 | ///
65 | public StringFormatMethodAttribute(string formatParameterName)
66 | {
67 | FormatParameterName = formatParameterName;
68 | }
69 |
70 | public string FormatParameterName { get; private set; }
71 | }
72 |
73 | ///
74 | /// Indicates that the function argument should be string literal and match one
75 | /// of the parameters of the caller function. For example, ReSharper annotates
76 | /// the parameter of
77 | ///
78 | ///
79 | /// public void Foo(string param) {
80 | /// if (param == null)
81 | /// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
82 | /// }
83 | ///
84 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
85 | public sealed class InvokerParameterNameAttribute : Attribute { }
86 |
87 | ///
88 | /// Indicates that the method is contained in a type that implements
89 | /// interface
90 | /// and this method is used to notify that some property value changed
91 | ///
92 | ///
93 | /// The method should be non-static and conform to one of the supported signatures:
94 | ///
95 | /// - NotifyChanged(string)
96 | /// - NotifyChanged(params string[])
97 | /// - NotifyChanged{T}(Expression{Func{T}})
98 | /// - NotifyChanged{T,U}(Expression{Func{T,U}})
99 | /// - SetProperty{T}(ref T, T, string)
100 | ///
101 | ///
102 | ///
103 | /// public class Foo : INotifyPropertyChanged {
104 | /// public event PropertyChangedEventHandler PropertyChanged;
105 | /// [NotifyPropertyChangedInvocator]
106 | /// protected virtual void NotifyChanged(string propertyName) { ... }
107 | ///
108 | /// private string _name;
109 | /// public string Name {
110 | /// get { return _name; }
111 | /// set { _name = value; NotifyChanged("LastName"); /* Warning */ }
112 | /// }
113 | /// }
114 | ///
115 | /// Examples of generated notifications:
116 | ///
117 | /// - NotifyChanged("Property")
118 | /// - NotifyChanged(() => Property)
119 | /// - NotifyChanged((VM x) => x.Property)
120 | /// - SetProperty(ref myField, value, "Property")
121 | ///
122 | ///
123 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
124 | public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
125 | {
126 | public NotifyPropertyChangedInvocatorAttribute() { }
127 | public NotifyPropertyChangedInvocatorAttribute(string parameterName)
128 | {
129 | ParameterName = parameterName;
130 | }
131 |
132 | public string ParameterName { get; private set; }
133 | }
134 |
135 | ///
136 | /// Describes dependency between method input and output
137 | ///
138 | ///
139 | /// Function Definition Table syntax:
140 | ///
141 | /// - FDT ::= FDTRow [;FDTRow]*
142 | /// - FDTRow ::= Input => Output | Output <= Input
143 | /// - Input ::= ParameterName: Value [, Input]*
144 | /// - Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}
145 | /// - Value ::= true | false | null | notnull | canbenull
146 | ///
147 | /// If method has single input parameter, it's name could be omitted.
148 | /// Using halt (or void/nothing, which is the same)
149 | /// for method output means that the methos doesn't return normally.
150 | /// canbenull annotation is only applicable for output parameters.
151 | /// You can use multiple [ContractAnnotation] for each FDT row,
152 | /// or use single attribute with rows separated by semicolon.
153 | ///
154 | ///
155 | ///
156 | /// [ContractAnnotation("=> halt")]
157 | /// public void TerminationMethod()
158 | ///
159 | ///
160 | /// [ContractAnnotation("halt <= condition: false")]
161 | /// public void Assert(bool condition, string text) // regular assertion method
162 | ///
163 | ///
164 | /// [ContractAnnotation("s:null => true")]
165 | /// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
166 | ///
167 | ///
168 | /// // A method that returns null if the parameter is null, and not null if the parameter is not null
169 | /// [ContractAnnotation("null => null; notnull => notnull")]
170 | /// public object Transform(object data)
171 | ///
172 | ///
173 | /// [ContractAnnotation("s:null=>false; =>true,result:notnull; =>false, result:null")]
174 | /// public bool TryParse(string s, out Person result)
175 | ///
176 | ///
177 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
178 | public sealed class ContractAnnotationAttribute : Attribute
179 | {
180 | public ContractAnnotationAttribute([NotNull] string contract)
181 | : this(contract, false) { }
182 |
183 | public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
184 | {
185 | Contract = contract;
186 | ForceFullStates = forceFullStates;
187 | }
188 |
189 | public string Contract { get; private set; }
190 | public bool ForceFullStates { get; private set; }
191 | }
192 |
193 | ///
194 | /// Indicates that marked element should be localized or not
195 | ///
196 | ///
197 | /// [LocalizationRequiredAttribute(true)]
198 | /// public class Foo {
199 | /// private string str = "my string"; // Warning: Localizable string
200 | /// }
201 | ///
202 | [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
203 | public sealed class LocalizationRequiredAttribute : Attribute
204 | {
205 | public LocalizationRequiredAttribute() : this(true) { }
206 | public LocalizationRequiredAttribute(bool required)
207 | {
208 | Required = required;
209 | }
210 |
211 | public bool Required { get; private set; }
212 | }
213 |
214 | ///
215 | /// Indicates that the value of the marked type (or its derivatives)
216 | /// cannot be compared using '==' or '!=' operators and Equals()
217 | /// should be used instead. However, using '==' or '!=' for comparison
218 | /// with null is always permitted.
219 | ///
220 | ///
221 | /// [CannotApplyEqualityOperator]
222 | /// class NoEquality { }
223 | /// class UsesNoEquality {
224 | /// public void Test() {
225 | /// var ca1 = new NoEquality();
226 | /// var ca2 = new NoEquality();
227 | /// if (ca1 != null) { // OK
228 | /// bool condition = ca1 == ca2; // Warning
229 | /// }
230 | /// }
231 | /// }
232 | ///
233 | [AttributeUsage(
234 | AttributeTargets.Interface | AttributeTargets.Class |
235 | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
236 | public sealed class CannotApplyEqualityOperatorAttribute : Attribute { }
237 |
238 | ///
239 | /// When applied to a target attribute, specifies a requirement for any type marked
240 | /// with the target attribute to implement or inherit specific type or types.
241 | ///
242 | ///
243 | /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
244 | /// public class ComponentAttribute : Attribute { }
245 | /// [Component] // ComponentAttribute requires implementing IComponent interface
246 | /// public class MyComponent : IComponent { }
247 | ///
248 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
249 | [BaseTypeRequired(typeof(Attribute))]
250 | public sealed class BaseTypeRequiredAttribute : Attribute
251 | {
252 | public BaseTypeRequiredAttribute([NotNull] Type baseType)
253 | {
254 | BaseType = baseType;
255 | }
256 |
257 | [NotNull] public Type BaseType { get; private set; }
258 | }
259 |
260 | ///
261 | /// Indicates that the marked symbol is used implicitly
262 | /// (e.g. via reflection, in external library), so this symbol
263 | /// will not be marked as unused (as well as by other usage inspections)
264 | ///
265 | [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
266 | public sealed class UsedImplicitlyAttribute : Attribute
267 | {
268 | public UsedImplicitlyAttribute()
269 | : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
270 |
271 | public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
272 | : this(useKindFlags, ImplicitUseTargetFlags.Default) { }
273 |
274 | public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
275 | : this(ImplicitUseKindFlags.Default, targetFlags) { }
276 |
277 | public UsedImplicitlyAttribute(
278 | ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
279 | {
280 | UseKindFlags = useKindFlags;
281 | TargetFlags = targetFlags;
282 | }
283 |
284 | public ImplicitUseKindFlags UseKindFlags { get; private set; }
285 | public ImplicitUseTargetFlags TargetFlags { get; private set; }
286 | }
287 |
288 | ///
289 | /// Should be used on attributes and causes ReSharper
290 | /// to not mark symbols marked with such attributes as unused
291 | /// (as well as by other usage inspections)
292 | ///
293 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
294 | public sealed class MeansImplicitUseAttribute : Attribute
295 | {
296 | public MeansImplicitUseAttribute()
297 | : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
298 |
299 | public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
300 | : this(useKindFlags, ImplicitUseTargetFlags.Default) { }
301 |
302 | public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
303 | : this(ImplicitUseKindFlags.Default, targetFlags) { }
304 |
305 | public MeansImplicitUseAttribute(
306 | ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
307 | {
308 | UseKindFlags = useKindFlags;
309 | TargetFlags = targetFlags;
310 | }
311 |
312 | [UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; }
313 | [UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; }
314 | }
315 |
316 | [Flags]
317 | public enum ImplicitUseKindFlags
318 | {
319 | Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
320 | /// Only entity marked with attribute considered used
321 | Access = 1,
322 | /// Indicates implicit assignment to a member
323 | Assign = 2,
324 | ///
325 | /// Indicates implicit instantiation of a type with fixed constructor signature.
326 | /// That means any unused constructor parameters won't be reported as such.
327 | ///
328 | InstantiatedWithFixedConstructorSignature = 4,
329 | /// Indicates implicit instantiation of a type
330 | InstantiatedNoFixedConstructorSignature = 8,
331 | }
332 |
333 | ///
334 | /// Specify what is considered used implicitly
335 | /// when marked with
336 | /// or
337 | ///
338 | [Flags]
339 | public enum ImplicitUseTargetFlags
340 | {
341 | Default = Itself,
342 | Itself = 1,
343 | /// Members of entity marked with attribute are considered used
344 | Members = 2,
345 | /// Entity marked with attribute and all its members considered used
346 | WithMembers = Itself | Members
347 | }
348 |
349 | ///
350 | /// This attribute is intended to mark publicly available API
351 | /// which should not be removed and so is treated as used
352 | ///
353 | [MeansImplicitUse]
354 | public sealed class PublicAPIAttribute : Attribute
355 | {
356 | public PublicAPIAttribute() { }
357 | public PublicAPIAttribute([NotNull] string comment)
358 | {
359 | Comment = comment;
360 | }
361 |
362 | [NotNull] public string Comment { get; private set; }
363 | }
364 |
365 | ///
366 | /// Tells code analysis engine if the parameter is completely handled
367 | /// when the invoked method is on stack. If the parameter is a delegate,
368 | /// indicates that delegate is executed while the method is executed.
369 | /// If the parameter is an enumerable, indicates that it is enumerated
370 | /// while the method is executed
371 | ///
372 | [AttributeUsage(AttributeTargets.Parameter, Inherited = true)]
373 | public sealed class InstantHandleAttribute : Attribute { }
374 |
375 | ///
376 | /// Indicates that a method does not make any observable state changes.
377 | /// The same as System.Diagnostics.Contracts.PureAttribute
378 | ///
379 | ///
380 | /// [Pure] private int Multiply(int x, int y) { return x * y; }
381 | /// public void Foo() {
382 | /// const int a = 2, b = 2;
383 | /// Multiply(a, b); // Waring: Return value of pure method is not used
384 | /// }
385 | ///
386 | [AttributeUsage(AttributeTargets.Method, Inherited = true)]
387 | public sealed class PureAttribute : Attribute { }
388 |
389 | ///
390 | /// Indicates that a parameter is a path to a file or a folder
391 | /// within a web project. Path can be relative or absolute,
392 | /// starting from web root (~)
393 | ///
394 | [AttributeUsage(AttributeTargets.Parameter)]
395 | public class PathReferenceAttribute : Attribute
396 | {
397 | public PathReferenceAttribute() { }
398 | public PathReferenceAttribute([PathReference] string basePath)
399 | {
400 | BasePath = basePath;
401 | }
402 |
403 | [NotNull] public string BasePath { get; private set; }
404 | }
405 |
406 | // ASP.NET MVC attributes
407 |
408 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
409 | public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute
410 | {
411 | public AspMvcAreaMasterLocationFormatAttribute(string format) { }
412 | }
413 |
414 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
415 | public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute
416 | {
417 | public AspMvcAreaPartialViewLocationFormatAttribute(string format) { }
418 | }
419 |
420 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
421 | public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute
422 | {
423 | public AspMvcAreaViewLocationFormatAttribute(string format) { }
424 | }
425 |
426 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
427 | public sealed class AspMvcMasterLocationFormatAttribute : Attribute
428 | {
429 | public AspMvcMasterLocationFormatAttribute(string format) { }
430 | }
431 |
432 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
433 | public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute
434 | {
435 | public AspMvcPartialViewLocationFormatAttribute(string format) { }
436 | }
437 |
438 | [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
439 | public sealed class AspMvcViewLocationFormatAttribute : Attribute
440 | {
441 | public AspMvcViewLocationFormatAttribute(string format) { }
442 | }
443 |
444 | ///
445 | /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
446 | /// is an MVC action. If applied to a method, the MVC action name is calculated
447 | /// implicitly from the context. Use this attribute for custom wrappers similar to
448 | /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)
449 | ///
450 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
451 | public sealed class AspMvcActionAttribute : Attribute
452 | {
453 | public AspMvcActionAttribute() { }
454 | public AspMvcActionAttribute([NotNull] string anonymousProperty)
455 | {
456 | AnonymousProperty = anonymousProperty;
457 | }
458 |
459 | [NotNull] public string AnonymousProperty { get; private set; }
460 | }
461 |
462 | ///
463 | /// ASP.NET MVC attribute. Indicates that a parameter is an MVC area.
464 | /// Use this attribute for custom wrappers similar to
465 | /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)
466 | ///
467 | [AttributeUsage(AttributeTargets.Parameter)]
468 | public sealed class AspMvcAreaAttribute : PathReferenceAttribute
469 | {
470 | public AspMvcAreaAttribute() { }
471 | public AspMvcAreaAttribute([NotNull] string anonymousProperty)
472 | {
473 | AnonymousProperty = anonymousProperty;
474 | }
475 |
476 | [NotNull] public string AnonymousProperty { get; private set; }
477 | }
478 |
479 | ///
480 | /// ASP.NET MVC attribute. If applied to a parameter, indicates that
481 | /// the parameter is an MVC controller. If applied to a method,
482 | /// the MVC controller name is calculated implicitly from the context.
483 | /// Use this attribute for custom wrappers similar to
484 | /// System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String)
485 | ///
486 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
487 | public sealed class AspMvcControllerAttribute : Attribute
488 | {
489 | public AspMvcControllerAttribute() { }
490 | public AspMvcControllerAttribute([NotNull] string anonymousProperty)
491 | {
492 | AnonymousProperty = anonymousProperty;
493 | }
494 |
495 | [NotNull] public string AnonymousProperty { get; private set; }
496 | }
497 |
498 | ///
499 | /// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master.
500 | /// Use this attribute for custom wrappers similar to
501 | /// System.Web.Mvc.Controller.View(String, String)
502 | ///
503 | [AttributeUsage(AttributeTargets.Parameter)]
504 | public sealed class AspMvcMasterAttribute : Attribute { }
505 |
506 | ///
507 | /// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type.
508 | /// Use this attribute for custom wrappers similar to
509 | /// System.Web.Mvc.Controller.View(String, Object)
510 | ///
511 | [AttributeUsage(AttributeTargets.Parameter)]
512 | public sealed class AspMvcModelTypeAttribute : Attribute { }
513 |
514 | ///
515 | /// ASP.NET MVC attribute. If applied to a parameter, indicates that
516 | /// the parameter is an MVC partial view. If applied to a method,
517 | /// the MVC partial view name is calculated implicitly from the context.
518 | /// Use this attribute for custom wrappers similar to
519 | /// System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String)
520 | ///
521 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
522 | public sealed class AspMvcPartialViewAttribute : PathReferenceAttribute { }
523 |
524 | ///
525 | /// ASP.NET MVC attribute. Allows disabling all inspections
526 | /// for MVC views within a class or a method.
527 | ///
528 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
529 | public sealed class AspMvcSupressViewErrorAttribute : Attribute { }
530 |
531 | ///
532 | /// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template.
533 | /// Use this attribute for custom wrappers similar to
534 | /// System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String)
535 | ///
536 | [AttributeUsage(AttributeTargets.Parameter)]
537 | public sealed class AspMvcDisplayTemplateAttribute : Attribute { }
538 |
539 | ///
540 | /// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template.
541 | /// Use this attribute for custom wrappers similar to
542 | /// System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String)
543 | ///
544 | [AttributeUsage(AttributeTargets.Parameter)]
545 | public sealed class AspMvcEditorTemplateAttribute : Attribute { }
546 |
547 | ///
548 | /// ASP.NET MVC attribute. Indicates that a parameter is an MVC template.
549 | /// Use this attribute for custom wrappers similar to
550 | /// System.ComponentModel.DataAnnotations.UIHintAttribute(System.String)
551 | ///
552 | [AttributeUsage(AttributeTargets.Parameter)]
553 | public sealed class AspMvcTemplateAttribute : Attribute { }
554 |
555 | ///
556 | /// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
557 | /// is an MVC view. If applied to a method, the MVC view name is calculated implicitly
558 | /// from the context. Use this attribute for custom wrappers similar to
559 | /// System.Web.Mvc.Controller.View(Object)
560 | ///
561 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
562 | public sealed class AspMvcViewAttribute : PathReferenceAttribute { }
563 |
564 | ///
565 | /// ASP.NET MVC attribute. When applied to a parameter of an attribute,
566 | /// indicates that this parameter is an MVC action name
567 | ///
568 | ///
569 | /// [ActionName("Foo")]
570 | /// public ActionResult Login(string returnUrl) {
571 | /// ViewBag.ReturnUrl = Url.Action("Foo"); // OK
572 | /// return RedirectToAction("Bar"); // Error: Cannot resolve action
573 | /// }
574 | ///
575 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
576 | public sealed class AspMvcActionSelectorAttribute : Attribute { }
577 |
578 | [AttributeUsage(
579 | AttributeTargets.Parameter | AttributeTargets.Property |
580 | AttributeTargets.Field, Inherited = true)]
581 | public sealed class HtmlElementAttributesAttribute : Attribute
582 | {
583 | public HtmlElementAttributesAttribute() { }
584 | public HtmlElementAttributesAttribute([NotNull] string name)
585 | {
586 | Name = name;
587 | }
588 |
589 | [NotNull] public string Name { get; private set; }
590 | }
591 |
592 | [AttributeUsage(
593 | AttributeTargets.Parameter | AttributeTargets.Field |
594 | AttributeTargets.Property, Inherited = true)]
595 | public sealed class HtmlAttributeValueAttribute : Attribute
596 | {
597 | public HtmlAttributeValueAttribute([NotNull] string name)
598 | {
599 | Name = name;
600 | }
601 |
602 | [NotNull] public string Name { get; private set; }
603 | }
604 |
605 | // Razor attributes
606 |
607 | ///
608 | /// Razor attribute. Indicates that a parameter or a method is a Razor section.
609 | /// Use this attribute for custom wrappers similar to
610 | /// System.Web.WebPages.WebPageBase.RenderSection(String)
611 | ///
612 | [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, Inherited = true)]
613 | public sealed class RazorSectionAttribute : Attribute { }
614 | }
--------------------------------------------------------------------------------
/src/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Insya.Localization")]
9 | [assembly: AssemblyDescription("Yasin Kuyu")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("www.insya.com")]
12 | [assembly: AssemblyProduct("")]
13 | [assembly: AssemblyCopyright("Copyright © 2014 Insya Bilisim Teknolojileri")]
14 | [assembly: AssemblyTrademark("(iBT) Insya Bilisim Teknolojileri")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("345aa916-743a-4d76-8ff3-5c3fae266f08")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.8.0")]
36 | [assembly: AssemblyFileVersion("1.0.8.0")]
37 |
--------------------------------------------------------------------------------
/src/Resource.cs:
--------------------------------------------------------------------------------
1 | // @yasinkuyu
2 | // 05/08/2014
3 |
4 | using System.Web;
5 | using System.Xml;
6 |
7 | namespace Insya.Localization
8 | {
9 | public class Resource
10 | {
11 | ///
12 | /// GetXmlResource all items (ex: tr_TR.xml)
13 | ///
14 | /// Very simple xml structure
15 | ///
16 | /// - Homepage
17 | ///
18 | ///
19 | ///
20 | ///
21 | public static void GetXmlResource(string path, string applicationName)
22 | {
23 | using (XmlTextReader reader = new XmlTextReader(path)) {
24 | XmlDocument xmlDoc = new XmlDocument();
25 | xmlDoc.Load(reader);
26 |
27 | var nodes = xmlDoc.DocumentElement.SelectSingleNode("//lang");
28 |
29 | for (int i = 0; i <= nodes.ChildNodes.Count - 1; i++) {
30 | string itemId = nodes.ChildNodes.Item(i).Attributes.Item(0).InnerText;
31 | string itemValue = nodes.ChildNodes.Item(i).InnerText;
32 |
33 | HttpContext.Current.Application[applicationName + itemId] = itemValue;
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------