diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml
new file mode 100644
index 0000000..5f3e48c
--- /dev/null
+++ b/.github/workflows/dotnet-core.yml
@@ -0,0 +1,17 @@
+name: .NET Core
+
+on: [push]
+
+jobs:
+ build:
+
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v1
+
+ - name: Build with dotnet
+ run: dotnet build --configuration Release
+
+ - name: Test
+ run: dotnet test --configuration Release
\ No newline at end of file
diff --git a/.github/workflows/nuget-master-publish.yml b/.github/workflows/nuget-master-publish.yml
new file mode 100644
index 0000000..9b5e85c
--- /dev/null
+++ b/.github/workflows/nuget-master-publish.yml
@@ -0,0 +1,40 @@
+# 去掉注释可以合并 master 分支自动打包
+# 为什么不期望推送 master 自动打包?原因是打出来的 CBB 没有 Tag 不利于回滚找到代码
+
+# name: publish nuget
+
+# on:
+# push:
+# branches:
+# - master
+
+# jobs:
+# build:
+
+# runs-on: windows-latest
+
+# steps:
+# - uses: actions/checkout@v1
+
+# - name: Setup .NET Core
+# uses: actions/setup-dotnet@v1
+# with:
+# dotnet-version: 3.1.300
+
+# - name: Build with dotnet
+# run: |
+# dotnet build --configuration Release
+# dotnet pack --configuration Release --no-build
+
+# - name: Install Nuget
+# uses: nuget/setup-nuget@v1
+# with:
+# nuget-version: '5.x'
+
+# - name: Add private GitHub registry to NuGet
+# run: |
+# nuget sources add -name github -Source https://nuget.pkg.github.com/dotnet-campus/index.json -Username dotnet-campus -Password ${{ secrets.GITHUB_TOKEN }}
+# - name: Push generated package to GitHub registry
+# run: |
+# nuget push .\bin\Release\*.nupkg -Source github -SkipDuplicate
+# nuget push .\bin\Release\*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NugetKey }}
diff --git a/.github/workflows/nuget-tag-publish.yml b/.github/workflows/nuget-tag-publish.yml
new file mode 100644
index 0000000..c2a1095
--- /dev/null
+++ b/.github/workflows/nuget-tag-publish.yml
@@ -0,0 +1,42 @@
+name: publish nuget
+
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ build:
+
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v1
+
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 8.0.x
+
+ - name: Install dotnet tool
+ run: dotnet tool install -g dotnetCampus.TagToVersion
+
+ - name: Set tag to version
+ run: dotnet TagToVersion -t ${{ github.ref }}
+
+ - name: Build with dotnet
+ run: dotnet build -c Release
+
+ - name: Install Nuget
+ uses: nuget/setup-nuget@v1
+ with:
+ nuget-version: '6.x'
+
+ - name: Add private GitHub registry to NuGet
+ run: |
+ nuget sources add -name github -Source https://nuget.pkg.github.com/dotnet-campus/index.json -Username dotnet-campus -Password ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Push generated package to GitHub registry
+ run: |
+ nuget push .\artifacts\package\release\*.nupkg -Source github -SkipDuplicate
+ nuget push .\artifacts\package\release\*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NugetKey }}
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..3d63a39
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ latest
+ enable
+ enable
+ $(MSBuildThisFileDirectory)artifacts
+ $(MSBuildThisFileDirectory)
+
+
+
+
+ 使用源生成器为你的项目增加本地化源代码,使得你可以利用 IDE 的智能感知来使用多语言。
+ dotnet-campus
+ dotnet campus(.NET 职业技术学院)
+ Copyright $([System.DateTime]::Now.ToString(`yyyy`)) © dotnet campus, All Rights Reserved.
+ git
+ https://github.com/dotnet-campus/dotnetCampus.SourceLocalizations
+ https://github.com/dotnet-campus/dotnetCampus.SourceLocalizations
+
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..85d6d8e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# dotnetCampus.SourceLocalizations
+
+| Build | NuGet |
+|--|--|
+|![](https://github.com/dotnet-campus/dotnetCampus.SourceLocalizations/workflows/.NET%20Core/badge.svg)|[![](https://img.shields.io/nuget/v/dotnetCampus.SourceLocalizations.svg)](https://www.nuget.org/packages/dotnetCampus.SourceLocalizations)|
diff --git a/build/Version.props b/build/Version.props
new file mode 100644
index 0000000..f1d2d98
--- /dev/null
+++ b/build/Version.props
@@ -0,0 +1,5 @@
+
+
+ 0.1.0-alpha01
+
+
diff --git a/dotnetCampus.SourceLocalizations.sln b/dotnetCampus.SourceLocalizations.sln
new file mode 100644
index 0000000..7f50212
--- /dev/null
+++ b/dotnetCampus.SourceLocalizations.sln
@@ -0,0 +1,57 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnetCampus.Localizations", "src\dotnetCampus.Localizations\dotnetCampus.Localizations.csproj", "{9A8FEE27-F589-48E4-BF31-CC0D5CD4A3F0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnetCampus.Localizations.Analyzer", "src\dotnetCampus.Localizations.Analyzer\dotnetCampus.Localizations.Analyzer.csproj", "{48BE5845-BF2F-48CD-8214-2418E72A9BFF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E407F54C-8E41-4F4E-B9BF-9864B6178E5F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalizationSample", "samples\LocalizationSample\LocalizationSample.csproj", "{F330175F-FC20-4D42-921A-747AC296D1B9}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4239BEE3-D480-4874-83E1-353B35F1BD86}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnetCampus.Localizations.Tests", "tests\dotnetCampus.Localizations.Tests\dotnetCampus.Localizations.Tests.csproj", "{3170B151-6A25-4321-BF09-EFC516E32F8D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{6E0F9A76-51AE-49A7-B74C-CA194F6CD37C}"
+ ProjectSection(SolutionItems) = preProject
+ .gitattributes = .gitattributes
+ .gitignore = .gitignore
+ README.md = README.md
+ Directory.Build.props = Directory.Build.props
+ build\Version.props = build\Version.props
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9A8FEE27-F589-48E4-BF31-CC0D5CD4A3F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9A8FEE27-F589-48E4-BF31-CC0D5CD4A3F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9A8FEE27-F589-48E4-BF31-CC0D5CD4A3F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9A8FEE27-F589-48E4-BF31-CC0D5CD4A3F0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {48BE5845-BF2F-48CD-8214-2418E72A9BFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {48BE5845-BF2F-48CD-8214-2418E72A9BFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {48BE5845-BF2F-48CD-8214-2418E72A9BFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {48BE5845-BF2F-48CD-8214-2418E72A9BFF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F330175F-FC20-4D42-921A-747AC296D1B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F330175F-FC20-4D42-921A-747AC296D1B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F330175F-FC20-4D42-921A-747AC296D1B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F330175F-FC20-4D42-921A-747AC296D1B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3170B151-6A25-4321-BF09-EFC516E32F8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3170B151-6A25-4321-BF09-EFC516E32F8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3170B151-6A25-4321-BF09-EFC516E32F8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3170B151-6A25-4321-BF09-EFC516E32F8D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {F330175F-FC20-4D42-921A-747AC296D1B9} = {E407F54C-8E41-4F4E-B9BF-9864B6178E5F}
+ {3170B151-6A25-4321-BF09-EFC516E32F8D} = {4239BEE3-D480-4874-83E1-353B35F1BD86}
+ EndGlobalSection
+EndGlobal
diff --git a/samples/LocalizationSample/LocalizationSample.csproj b/samples/LocalizationSample/LocalizationSample.csproj
new file mode 100644
index 0000000..30de8fd
--- /dev/null
+++ b/samples/LocalizationSample/LocalizationSample.csproj
@@ -0,0 +1,16 @@
+
+
+
+ WinExe
+ net8.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/LocalizationSample/Localizations/en.yaml b/samples/LocalizationSample/Localizations/en.yaml
new file mode 100644
index 0000000..c5e80fa
--- /dev/null
+++ b/samples/LocalizationSample/Localizations/en.yaml
@@ -0,0 +1,3 @@
+A.A1: "Words"
+A.A2: "Error code: {errorCode:int}"
+A.A3: "Error: {error}"
diff --git a/samples/LocalizationSample/Localizations/zh-hans.yaml b/samples/LocalizationSample/Localizations/zh-hans.yaml
new file mode 100644
index 0000000..b38d5cd
--- /dev/null
+++ b/samples/LocalizationSample/Localizations/zh-hans.yaml
@@ -0,0 +1,3 @@
+A.A1: "文本"
+A.A2: "错误码:{errorCode:int}"
+A.A3: "错误:{error}"
diff --git a/samples/LocalizationSample/Program.cs b/samples/LocalizationSample/Program.cs
new file mode 100644
index 0000000..7ffbdf9
--- /dev/null
+++ b/samples/LocalizationSample/Program.cs
@@ -0,0 +1,61 @@
+using System.Collections.Frozen;
+using System.ComponentModel;
+using dotnetCampus.Localizations;
+
+namespace LocalizationSample;
+
+internal class Program
+{
+ public static void Main(string[] args)
+ {
+ }
+}
+
+[LocalizedConfiguration(Default = "zh-hans", Current = "en")]
+internal partial class Lang;
+
+[EditorBrowsable(EditorBrowsableState.Never)]
+public interface ILocalized_Root : ILocalizedStringProvider
+{
+ ILocalized_Root_A A => (ILocalized_Root_A)this;
+}
+
+[EditorBrowsable(EditorBrowsableState.Never)]
+public interface ILocalized_Root_A : ILocalizedStringProvider
+{
+ LocalizedString A1 => this.Get0("A.A1");
+
+ LocalizedString A2 => this.Get1("A.A2");
+
+ LocalizedString