From a79d7459e96c9d147e14a30cefba0932b14dfa0b Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Sat, 8 Aug 2026 10:34:26 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E9=87=8D=E5=86=99=E5=88=B0C#?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 40 +++++------ language.cs | 128 ++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 20 deletions(-) create mode 100644 language.cs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e3d4148..ba81a6e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,40 +1,40 @@ name: 构建二进制可执行文件 on: + pull_request: + paths: + - "language.cs" + # 只在源代码被更新时运行 workflow_dispatch: push: paths: - - "language.cpp" - # 只在源代码被更新时运行 - + - "language.cs" jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.runner }} + container: alpine:latest strategy: matrix: include: - - target: x86_64-linux-musl + - runner: ubuntu-latest artifact: language - - target: aarch64-linux-musl + - runner: ubuntu-26.04-arm artifact: language_arm steps: - - uses: actions/checkout@v6 - - name: 下载 musl 工具链 - uses: lmq8267/dl-musl@main - with: - target: ${{ matrix.target }} - static: true + - uses: actions/checkout@v7 + - name: 安装依赖项 + run: | + apk update + apk add build-base dotnet10-sdk clang - name: 编译 - run: | - if [ "${{ matrix.target }}" = "x86_64-linux-musl" ]; then - "$CXX" -o "${{ matrix.artifact }}" -std=c++23 -s --static language.cpp - else - "$CXX" -o "${{ matrix.artifact }}" -std=c++23 -s --static language.cpp - fi - - - uses: actions/upload-artifact@v5 + run: + dotnet publish language.cs + - name: 重命名 + if: ${{ matrix.runner == 'ubuntu-26.04-arm' }} + run: mv artifacts/language/language artifacts/language/language_arm + - uses: actions/upload-artifact@v7 with: name: ${{ matrix.artifact }} path: ${{ matrix.artifact }} \ No newline at end of file diff --git a/language.cs b/language.cs new file mode 100644 index 0000000..8734953 --- /dev/null +++ b/language.cs @@ -0,0 +1,128 @@ +#:property PublishAot=true +#:property StaticExecutable=true +#:property OptimizationPreference=Speed +// #:property OptimizationPreference=Size +// #:property InvariantGlobalization=true +// #:property StackTraceSupport=false + +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; + +[DllImport("libc", EntryPoint = "geteuid")] +static extern uint GetEffectiveUserId(); + +bool CheckUser(string DisplayMessage = "即将开始更新语言配置"){ + if (DisplayMessage != null){ + Console.WriteLine(DisplayMessage); } + Console.WriteLine("按回车继续,按Esc取消"); + while (true){ + var KeyInfo = Console.ReadKey(true); + if (KeyInfo.Key == ConsoleKey.Enter){ + return true; } + else if (KeyInfo.Key == ConsoleKey.Escape){ + return false; } } } + +bool IsRunningInsideWSL(){ + string VersionFile = File.ReadAllText("/proc/version"); + string KernelOsReleaseFile = File.ReadAllText("/proc/sys/kernel/osrelease"); + if (VersionFile.Contains("Microsoft") || VersionFile.Contains("WSL")){ + return true; } + if (KernelOsReleaseFile.Contains("microsoft") || KernelOsReleaseFile.Contains("WSL")){ + return true; } + return false; } + +bool ExecuteCommand(string Command, + List? Arguments = null, + Action? WhenErrorThrown = null){ + List StandardError = []; + int ExitCode = 0; + + try{ + using var Process = new Process(); + Process.StartInfo.FileName = Command; + if (Arguments != null){ + foreach (var Argument in Arguments){ + Process.StartInfo.ArgumentList.Add(Argument); } } + Process.StartInfo.RedirectStandardError = true; + Process.ErrorDataReceived += (_, Event) => { + if (Event.Data != null){ + Console.WriteLine(Event.Data); + StandardError.Add(Event.Data + "\n"); } }; + Process.Start(); + Process.BeginOutputReadLine(); + Process.BeginErrorReadLine(); + Process.WaitForExit(); + ExitCode = Process.ExitCode; + if (ExitCode != 0){ + WhenErrorThrown?.Invoke(ExitCode, string.Join("\n", StandardError), null); + return false; } + return true; } + catch (Exception ExceptionInstance){ + WhenErrorThrown ??= (ExitCode, StandardError, ExceptionMessage) => { + Console.WriteLine(@$" + 命令执行失败 + 退出代码: {ExitCode} + stderr: {StandardError} + 异常信息: {ExceptionMessage}"); }; + WhenErrorThrown(ExitCode, string.Join("\n", StandardError), ExceptionInstance.Message); + return false; } } + +if (Enum.TryParse(RuntimeInformation.OSDescription, out var CurrentSystem) == false){ + string CurrentSuppoetedLinuxDistributions = string.Join(", ", Enum.GetNames()); + string Message = @$" + 当前系统为 {RuntimeInformation.OSDescription} + 当前仅支持 {CurrentSuppoetedLinuxDistributions} + 强行使用可能会造成不可预知的问题 + 为避免出现故障,程序会强制退出 + 如果是误报,请在GitHub仓库打开一个新的issue。 + ".Trim(); + throw new NotSupportedException(Message); } +if (GetEffectiveUserId() != 0){ + throw new UnauthorizedAccessException("更改语言文件需要root权限,请使用sudo重新运行本程序"); } + +Console.WriteLine($"探测到当前系统为 {RuntimeInformation.OSDescription}"); +switch (CurrentSystem){ + case SupportedLinuxDistributions.Debian or SupportedLinuxDistributions.Armbian: { + CheckUser(); + Console.WriteLine("正在检查语言配置"); + using var FileStream = new FileStream("/etc/locale.gen", FileMode.Create, FileAccess.ReadWrite, FileShare.None); + var NewContent = File.ReadLines("/etc/locale.gen") + .Select(Line => Line.Trim()) + .Select(Line => { + if (Line.Contains("zh_CN.UTF-8 UTF-8")){ + Line = "zh_CN.UTF-8 UTF-8"; } + return Line; } ) + .ToArray(); + FileStream.SetLength(0); + FileStream.Seek(0, SeekOrigin.Begin); + using var StreamWriter = new StreamWriter(FileStream, Encoding.UTF8); + foreach (var Line in NewContent){ + StreamWriter.WriteLine(Line); } + break; } + case SupportedLinuxDistributions.Ubuntu: { + CheckUser("即将开始安装中文语言包"); + Console.WriteLine("正在更新apt软件包源"); + ExecuteCommand("apt", ["update"]); + Console.WriteLine("正在安装中文语言包"); + ExecuteCommand("apt", ["install", "language-pack-zh-hans", "-y"]); + Console.WriteLine("正在更新语言配置"); + ExecuteCommand("update-locale", ["LANG=zh_CN.UTF-8"]); + break; } + case SupportedLinuxDistributions.ArchLinux: { + CheckUser(); + Console.WriteLine("开始更新语言配置"); + ExecuteCommand("localectl", ["set-locale", "LANG=zh_CN.UTF-8"]); + if (IsRunningInsideWSL()){ + // https://wiki.archlinuxcn.org/wiki/%E5%9C%A8_WSL_%E4%B8%8A%E5%AE%89%E8%A3%85_Arch_Linux#%E4%BF%AE%E6%94%B9%E5%8C%BA%E5%9F%9F%E8%AE%BE%E7%BD%AE + Console.WriteLine("检测到您正在WSL中运行Arch Linux,正在创建 /etc/locale.conf -> /etc/default/locale 符号链接"); + File.CreateSymbolicLink("/etc/locale.conf", "/etc/default/locale"); } + break; } } +Console.WriteLine("配置完成,更改将在您下一次登录Shell时生效,按任意键退出"); +Console.ReadKey(true); + +enum SupportedLinuxDistributions { + Debian, + Armbian, + Ubuntu, + ArchLinux } \ No newline at end of file From 1e633b0e8bd8e55c03f0dfca68e34fe5d86bedfd Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Sat, 8 Aug 2026 11:00:04 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8DARM64=E4=B8=8B=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E8=BF=90=E8=A1=8CAction=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 22 ++++++++++++---------- .gitignore | 12 ++---------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ba81a6e..2d01fd3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,11 +1,11 @@ name: 构建二进制可执行文件 on: + workflow_dispatch: pull_request: paths: - "language.cs" # 只在源代码被更新时运行 - workflow_dispatch: push: paths: - "language.cs" @@ -13,8 +13,8 @@ jobs: build: runs-on: ${{ matrix.runner }} - container: alpine:latest strategy: + fail-fast: false matrix: include: - runner: ubuntu-latest @@ -23,18 +23,20 @@ jobs: artifact: language_arm steps: - uses: actions/checkout@v7 - - name: 安装依赖项 - run: | - apk update - apk add build-base dotnet10-sdk clang - name: 编译 - run: - dotnet publish language.cs + run: | + docker run --rm \ + -v "${{ github.workspace }}":/src \ + -w /src \ + alpine:latest /bin/sh -c ' + apk update + apk add build-base dotnet10-sdk clang + dotnet publish language.cs ' - name: 重命名 if: ${{ matrix.runner == 'ubuntu-26.04-arm' }} - run: mv artifacts/language/language artifacts/language/language_arm + run: sudo mv artifacts/language/language artifacts/language/language_arm - uses: actions/upload-artifact@v7 with: name: ${{ matrix.artifact }} - path: ${{ matrix.artifact }} \ No newline at end of file + path: artifacts/language/${{ matrix.artifact }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index ca3423e..b8395df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,2 @@ -################################################################################ -# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 -################################################################################ - -.vs -.vscode -a.out -build -language -language_arm \ No newline at end of file +.vscode +artifacts \ No newline at end of file From 3493263324cb9715bbfba7bf9a5771a16d675cea Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Sat, 8 Aug 2026 11:15:22 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E4=BA=8E=E5=8F=AF=E8=83=BD=E4=B8=8D=E5=AD=98=E5=9C=A8=E7=9A=84?= =?UTF-8?q?libicu=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- language.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language.cs b/language.cs index 8734953..4d148a8 100644 --- a/language.cs +++ b/language.cs @@ -2,7 +2,7 @@ #:property StaticExecutable=true #:property OptimizationPreference=Speed // #:property OptimizationPreference=Size -// #:property InvariantGlobalization=true +#:property InvariantGlobalization=true // #:property StackTraceSupport=false using System.Diagnostics; From d4550e240ca374e635c1c7f61941449423dc8423 Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Sat, 8 Aug 2026 11:57:06 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E5=AF=B9=E9=83=A8=E5=88=86TryParse?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E7=9B=B4=E6=8E=A5=E5=AE=8C=E6=88=90=E6=98=A0?= =?UTF-8?q?=E5=B0=84=E7=9A=84=E7=B3=BB=E7=BB=9F=E8=BF=9B=E8=A1=8C=E7=89=B9?= =?UTF-8?q?=E5=88=A4=20=E8=99=BD=E7=84=B6=E7=8E=B0=E5=9C=A8=E5=8F=AA?= =?UTF-8?q?=E8=A6=81ArchLinux=E4=B8=80=E4=B8=AA=EF=BC=8C=E4=BD=86=E4=B9=8B?= =?UTF-8?q?=E5=90=8E=E5=BA=94=E8=AF=A5=E4=BC=9A=E5=8F=98=E6=88=90=E9=83=A8?= =?UTF-8?q?=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- language.cs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/language.cs b/language.cs index 4d148a8..769d606 100644 --- a/language.cs +++ b/language.cs @@ -67,21 +67,24 @@ bool ExecuteCommand(string Command, 异常信息: {ExceptionMessage}"); }; WhenErrorThrown(ExitCode, string.Join("\n", StandardError), ExceptionInstance.Message); return false; } } - -if (Enum.TryParse(RuntimeInformation.OSDescription, out var CurrentSystem) == false){ - string CurrentSuppoetedLinuxDistributions = string.Join(", ", Enum.GetNames()); - string Message = @$" - 当前系统为 {RuntimeInformation.OSDescription} - 当前仅支持 {CurrentSuppoetedLinuxDistributions} - 强行使用可能会造成不可预知的问题 - 为避免出现故障,程序会强制退出 - 如果是误报,请在GitHub仓库打开一个新的issue。 - ".Trim(); - throw new NotSupportedException(Message); } +string OsDescription = RuntimeInformation.OSDescription; +if (Enum.TryParse(OsDescription.Split(' ')[0], out var CurrentSystem) == false){ + if (OsDescription.Contains("Arch Linux")){ + CurrentSystem = SupportedLinuxDistributions.ArchLinux; } + else{ + string CurrentSuppoetedLinuxDistributions = string.Join(", ", Enum.GetNames()); + string Message = @$" + 当前系统为 {OsDescription} + 当前仅支持 {CurrentSuppoetedLinuxDistributions} + 强行使用可能会造成不可预知的问题 + 为避免出现故障,程序会强制退出 + 如果是误报,请在GitHub仓库打开一个新的issue。 + ".Trim(); + throw new NotSupportedException(Message); } } if (GetEffectiveUserId() != 0){ throw new UnauthorizedAccessException("更改语言文件需要root权限,请使用sudo重新运行本程序"); } -Console.WriteLine($"探测到当前系统为 {RuntimeInformation.OSDescription}"); +Console.WriteLine($"探测到当前系统为 {OsDescription}"); switch (CurrentSystem){ case SupportedLinuxDistributions.Debian or SupportedLinuxDistributions.Armbian: { CheckUser(); From d5cf0c9910f0dda9bda2ccacadde919375859d4c Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Sat, 8 Aug 2026 12:19:54 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E4=BF=AE=E7=BC=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 +++++++++++++++++++++++++++++++++- language.cs | 6 +++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9c844bb..ef086f6 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,36 @@ wget https://github.com/TheWhiteDog9487/lag2cn/releases/latest/download/language chmod +x language_arm ./language_arm rm language_arm -``` \ No newline at end of file +``` + +## 关于可用性 +对每一个系统版本进行实际测试是不现实的,我会尽量保证可用性,但是更新之后的测试只会在最新版本进行 +并且,由于各种系统版本众多来源复杂,哪怕是最新版本也未必100%可用 +故此,如果您在使用过程中遇到问题,请在GitHub仓库打开一个新的issue,我会尽力处理 + +## 如果你想自行编译 +最低依赖项: +- .NET 10 SDK +- 任意C++编译器 + +推荐依赖项: +- Alpine Linux +- .NET 10 SDK +- Clang +- build-base + +推荐使用AlpineLinux进行编译,因为Alpine的系统libc就是musl,编译出的产物可以直接用而不需要管目标系统glibc的版本问题 +您可以使用下面的Docker命令获得一个Alpine环境 +```shell +docker run --rm -it -v .:/src -w /src alpine +``` +安装依赖项 +```shell +apk update +apk add clang build-base dotnet10-sdk +``` +然后进行编译 +```shell +dotnet publish language.cs +``` +你需要的ELF会出现在`artifacts/language/`文件夹内 \ No newline at end of file diff --git a/language.cs b/language.cs index 769d606..7404de3 100644 --- a/language.cs +++ b/language.cs @@ -1,3 +1,6 @@ +#!/usr/bin/env -S dotnet -- +// https://learn.microsoft.com/zh-cn/dotnet/core/sdk/file-based-apps + #:property PublishAot=true #:property StaticExecutable=true #:property OptimizationPreference=Speed @@ -128,4 +131,5 @@ enum SupportedLinuxDistributions { Debian, Armbian, Ubuntu, - ArchLinux } \ No newline at end of file + ArchLinux, + CachyOS } \ No newline at end of file From 1cfa17d3408075a25ee136d68f9ec8ff6f1d3fde Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Sat, 8 Aug 2026 13:52:24 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BE=88=E5=A4=9A?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- language.cpp | 152 --------------------------------------------------- language.cs | 61 +++++++++++---------- 2 files changed, 33 insertions(+), 180 deletions(-) delete mode 100644 language.cpp diff --git a/language.cpp b/language.cpp deleted file mode 100644 index a469dae..0000000 --- a/language.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace std; - -enum class System{ - Ubuntu, - Debian, - ArchLinux, - Unsupported }; -enum class User{ - Root, - Other }; - -auto CheckIfRunningInsideWSL(){ - if (filesystem::exists("/proc/version")) { - ifstream version_file("/proc/version"); - string version_info = ""; - getline(version_file, version_info); - if (version_info.find("Microsoft") != string::npos or - version_info.find("WSL") != string::npos) { - return true; } - version_file.close(); } - if (filesystem::exists("/proc/sys/kernel/osrelease")) { - ifstream osrelease_file("/proc/sys/kernel/osrelease"); - string osrelease_info = ""; - getline(osrelease_file, osrelease_info); - if (osrelease_info.find("microsoft") != string::npos or - osrelease_info.find("WSL") != string::npos) { - return true; } - osrelease_file.close(); } - return false; } - -auto GetCurrentUser(){ - if (getenv("USER") != nullptr){ - string user = getenv("USER"); - if (user == "root" or geteuid() == 0){ - return User::Root; } - else{ - return User::Other; } } - else{ - throw runtime_error("无法获取用户信息"); } } - -/// @brief 获取当前系统的发行版名称 -/// @return 发行版名称,带有版本号 -/// @author ChatGPT -auto GetCurrentSystem() { - string distro_name = ""; - ifstream release_file("/etc/os-release"); - if (release_file.is_open()) { - string line = ""; - while (getline(release_file, line)) { - if (line.find("PRETTY_NAME=") != string::npos) { - distro_name = line.substr(line.find("=") + 1); - distro_name.erase(0, 1); // remove opening quote - distro_name.erase(distro_name.size() - 1); // remove closing quote - break; } } - release_file.close(); } - - if(distro_name.find("Ubuntu") != string::npos){ - return pair(System::Ubuntu, distro_name); } - else if(distro_name.find("Debian") != string::npos or - distro_name.find("Armbian") != string::npos){ - return pair(System::Debian, distro_name); } - else if(distro_name.find("Arch Linux") != string::npos or - distro_name.find("CachyOS") != string::npos){ - return pair(System::ArchLinux, distro_name); } - else{ - return pair(System::Unsupported, distro_name); } } - -auto check() { - cout << "请输入您的选项(输入y或者yes继续)"; - string userin = ""; - cin >> userin; - if (userin == "y" or userin == "yes") - return; - else{ - cout << "输入不正确欸,如果想停止本程序的话请按下Ctrl+C" << endl; - check(); } } - -auto Ubuntu(){ - cout << "即将开始安装并配置简体中文语言包,请输入y或者yes继续,或者按Ctrl+C终止本程序"; - check(); - cout << "开始更新语言配置" << endl; - system("apt update"); - system("apt install -y language-pack-zh-hans"); - system("update-locale LANG=zh_CN.UTF-8"); - cout << "配置完成,更改将在您下一次登录Shell时应用" << endl; } - -auto Debian(){ - cout << "即将开始更新语言配置,请输入y或者yes继续,或者按Ctrl+C终止本程序"; - check(); - cout << "开始更新语言配置" << endl; - fstream locale_gen("/etc/locale.gen"); - if (locale_gen.is_open() == false){ - throw system_error(errno, system_category(), "未能正确打开/etc/locale.gen"); } - vector FileContent; - string Buffer = ""; - while (getline(locale_gen, Buffer)){ - FileContent.push_back(Buffer); } - for (auto& Line : FileContent){ - if (Line == "zh_CN.UTF-8 UTF-8"){ - goto skip_write; } } - locale_gen.clear(); - locale_gen.seekp(0, ios::end); - locale_gen << '\n' << "zh_CN.UTF-8 UTF-8" << endl; -skip_write: - locale_gen.close(); - system("locale-gen"); - system("update-locale LANG=zh_CN.UTF-8"); - cout << "配置完成,更改将在您下一次登录Shell时应用" << endl; } - -auto ArchLinux(){ - // https://wiki.archlinuxcn.org/wiki/Locale - cout << "即将开始更新语言配置,请输入y或者yes继续,或者按Ctrl+C终止本程序"; - check(); - cout << "开始更新语言配置" << endl; - system("localectl set-locale LANG=zh_CN.UTF-8"); - if (CheckIfRunningInsideWSL() == true){ - // https://wiki.archlinuxcn.org/wiki/%E5%9C%A8_WSL_%E4%B8%8A%E5%AE%89%E8%A3%85_Arch_Linux#%E4%BF%AE%E6%94%B9%E5%8C%BA%E5%9F%9F%E8%AE%BE%E7%BD%AE - cout << "检测到您正在WSL中运行Arch Linux,正在创建 /etc/locale.conf -> /etc/default/locale 符号链接" << endl; - filesystem::create_symlink("/etc/locale.conf", "/etc/default/locale"); } - cout << "配置完成,更改将在您下一次登录Shell时应用" << endl; } - -auto ThrowUnsupportedSystemError(){ - cout << "错误:未知操作系统" << endl - << "当前仅适配了Ubuntu,Debian和Arch Linux" << endl - << "强行使用可能会造成不可预知的问题" << endl - << "为避免出现故障,程序会强制退出" << endl - << "如果是误报,请在GitHub仓库打开一个新的issue。" << endl; - throw runtime_error("不支持的操作系统"); } - -int main() { - auto OsType = GetCurrentSystem(); - if (OsType.first == System::Unsupported){ - ThrowUnsupportedSystemError(); } - - if (GetCurrentUser() == User::Other){ - cout << "更改语言文件需要root权限,请使用sudo重新运行本程序" << endl; - throw runtime_error("权限不足"); } - - cout << "检测到您使用的系统为:" << OsType.second << endl; - if (OsType.first == System::Ubuntu){ Ubuntu(); } - if (OsType.first == System::Debian){ Debian(); } - if (OsType.first == System::ArchLinux){ ArchLinux(); } } \ No newline at end of file diff --git a/language.cs b/language.cs index 7404de3..ac1baa3 100644 --- a/language.cs +++ b/language.cs @@ -15,16 +15,15 @@ using System.Text; [DllImport("libc", EntryPoint = "geteuid")] static extern uint GetEffectiveUserId(); -bool CheckUser(string DisplayMessage = "即将开始更新语言配置"){ - if (DisplayMessage != null){ - Console.WriteLine(DisplayMessage); } +void CheckUser(string DisplayMessage = "即将开始更新语言配置"){ + Console.WriteLine(DisplayMessage); Console.WriteLine("按回车继续,按Esc取消"); while (true){ var KeyInfo = Console.ReadKey(true); if (KeyInfo.Key == ConsoleKey.Enter){ - return true; } + return; } else if (KeyInfo.Key == ConsoleKey.Escape){ - return false; } } } + Environment.Exit(0); } } } bool IsRunningInsideWSL(){ string VersionFile = File.ReadAllText("/proc/version"); @@ -35,7 +34,7 @@ bool IsRunningInsideWSL(){ return true; } return false; } -bool ExecuteCommand(string Command, +void ExecuteCommand(string Command, List? Arguments = null, Action? WhenErrorThrown = null){ List StandardError = []; @@ -53,32 +52,30 @@ bool ExecuteCommand(string Command, Console.WriteLine(Event.Data); StandardError.Add(Event.Data + "\n"); } }; Process.Start(); - Process.BeginOutputReadLine(); Process.BeginErrorReadLine(); Process.WaitForExit(); ExitCode = Process.ExitCode; if (ExitCode != 0){ - WhenErrorThrown?.Invoke(ExitCode, string.Join("\n", StandardError), null); - return false; } - return true; } + throw new Exception($"命令执行失败,退出代码: {ExitCode}"); } } catch (Exception ExceptionInstance){ WhenErrorThrown ??= (ExitCode, StandardError, ExceptionMessage) => { Console.WriteLine(@$" 命令执行失败 退出代码: {ExitCode} stderr: {StandardError} - 异常信息: {ExceptionMessage}"); }; + 异常信息: {ExceptionMessage ?? ""}"); }; WhenErrorThrown(ExitCode, string.Join("\n", StandardError), ExceptionInstance.Message); - return false; } } + throw; } } + string OsDescription = RuntimeInformation.OSDescription; if (Enum.TryParse(OsDescription.Split(' ')[0], out var CurrentSystem) == false){ if (OsDescription.Contains("Arch Linux")){ CurrentSystem = SupportedLinuxDistributions.ArchLinux; } else{ - string CurrentSuppoetedLinuxDistributions = string.Join(", ", Enum.GetNames()); + string CurrentSupportedLinuxDistributions = string.Join(", ", Enum.GetNames()); string Message = @$" 当前系统为 {OsDescription} - 当前仅支持 {CurrentSuppoetedLinuxDistributions} + 当前仅支持 {CurrentSupportedLinuxDistributions} 强行使用可能会造成不可预知的问题 为避免出现故障,程序会强制退出 如果是误报,请在GitHub仓库打开一个新的issue。 @@ -92,20 +89,26 @@ switch (CurrentSystem){ case SupportedLinuxDistributions.Debian or SupportedLinuxDistributions.Armbian: { CheckUser(); Console.WriteLine("正在检查语言配置"); - using var FileStream = new FileStream("/etc/locale.gen", FileMode.Create, FileAccess.ReadWrite, FileShare.None); - var NewContent = File.ReadLines("/etc/locale.gen") + string[] NewContent = []; + using var FileStream = new FileStream("/etc/locale.gen", FileMode.Open, FileAccess.ReadWrite, FileShare.None); + using (var StreamReader = new StreamReader(FileStream, Encoding.UTF8, true, 1024, true)){ + NewContent = [.. StreamReader.ReadToEnd() + .Split("\n") .Select(Line => Line.Trim()) .Select(Line => { if (Line.Contains("zh_CN.UTF-8 UTF-8")){ Line = "zh_CN.UTF-8 UTF-8"; } - return Line; } ) - .ToArray(); - FileStream.SetLength(0); - FileStream.Seek(0, SeekOrigin.Begin); - using var StreamWriter = new StreamWriter(FileStream, Encoding.UTF8); + return Line; } ) ]; } + FileStream.SetLength(0); + FileStream.Seek(0, SeekOrigin.Begin); + using (var StreamWriter = new StreamWriter(FileStream, Encoding.UTF8)){ foreach (var Line in NewContent){ - StreamWriter.WriteLine(Line); } - break; } + StreamWriter.WriteLine(Line); } } + Console.WriteLine("正在生成语言配置"); + ExecuteCommand("locale-gen"); + Console.WriteLine("正在更新语言配置"); + ExecuteCommand("update-locale", ["LANG=zh_CN.UTF-8"]); + break; } case SupportedLinuxDistributions.Ubuntu: { CheckUser("即将开始安装中文语言包"); Console.WriteLine("正在更新apt软件包源"); @@ -115,15 +118,17 @@ switch (CurrentSystem){ Console.WriteLine("正在更新语言配置"); ExecuteCommand("update-locale", ["LANG=zh_CN.UTF-8"]); break; } - case SupportedLinuxDistributions.ArchLinux: { + case SupportedLinuxDistributions.ArchLinux or SupportedLinuxDistributions.CachyOS: { CheckUser(); Console.WriteLine("开始更新语言配置"); ExecuteCommand("localectl", ["set-locale", "LANG=zh_CN.UTF-8"]); if (IsRunningInsideWSL()){ - // https://wiki.archlinuxcn.org/wiki/%E5%9C%A8_WSL_%E4%B8%8A%E5%AE%89%E8%A3%85_Arch_Linux#%E4%BF%AE%E6%94%B9%E5%8C%BA%E5%9F%9F%E8%AE%BE%E7%BD%AE - Console.WriteLine("检测到您正在WSL中运行Arch Linux,正在创建 /etc/locale.conf -> /etc/default/locale 符号链接"); - File.CreateSymbolicLink("/etc/locale.conf", "/etc/default/locale"); } - break; } } + // https://wiki.archlinuxcn.org/wiki/%E5%9C%A8_WSL_%E4%B8%8A%E5%AE%89%E8%A3%85_Arch_Linux#%E4%BF%AE%E6%94%B9%E5%8C%BA%E5%9F%9F%E8%AE%BE%E7%BD%AE + Console.WriteLine("检测到您正在WSL中运行Arch Linux,正在创建 /etc/locale.conf -> /etc/default/locale 符号链接"); + if (File.Exists("/etc/default/locale")){ + File.Move("/etc/default/locale", "/etc/default/locale.bak", true); } + File.CreateSymbolicLink("/etc/default/locale", "/etc/locale.conf"); } + break; } } Console.WriteLine("配置完成,更改将在您下一次登录Shell时生效,按任意键退出"); Console.ReadKey(true); From 7913305260a62d479d3d58d526ff13fe1e0d2d5c Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Tue, 11 Aug 2026 16:27:17 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E5=BD=BB=E5=BA=95=E7=A7=BB=E9=99=A4P/Invok?= =?UTF-8?q?e=EF=BC=8C=E4=BB=A5=E8=A7=A3=E5=86=B3=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E6=97=B6DLL=E6=89=BE=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20=E8=99=BD=E7=84=B6=E4=B8=8D=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E8=B0=83=E7=94=A8libc=E4=BA=86=EF=BC=8C=E4=BD=86=E6=98=AF?= =?UTF-8?q?=E4=BB=8D=E7=84=B6=E9=9C=80=E8=A6=81=E9=9D=99=E6=80=81=E9=93=BE?= =?UTF-8?q?=E6=8E=A5=EF=BC=8C=E4=B8=8D=E7=84=B6=E8=BF=98=E6=98=AF=E4=BC=9A?= =?UTF-8?q?=E5=87=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- language.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/language.cs b/language.cs index ac1baa3..bb2b049 100644 --- a/language.cs +++ b/language.cs @@ -6,15 +6,13 @@ #:property OptimizationPreference=Speed // #:property OptimizationPreference=Size #:property InvariantGlobalization=true +// ↑ 这个东西需要libicu // #:property StackTraceSupport=false using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; -[DllImport("libc", EntryPoint = "geteuid")] -static extern uint GetEffectiveUserId(); - void CheckUser(string DisplayMessage = "即将开始更新语言配置"){ Console.WriteLine(DisplayMessage); Console.WriteLine("按回车继续,按Esc取消"); @@ -81,7 +79,7 @@ if (Enum.TryParse(OsDescription.Split(' ')[0], out 如果是误报,请在GitHub仓库打开一个新的issue。 ".Trim(); throw new NotSupportedException(Message); } } -if (GetEffectiveUserId() != 0){ +if (Environment.IsPrivilegedProcess == false){ throw new UnauthorizedAccessException("更改语言文件需要root权限,请使用sudo重新运行本程序"); } Console.WriteLine($"探测到当前系统为 {OsDescription}"); From e603b7d733e5dab2869138654ddf530486e26647 Mon Sep 17 00:00:00 2001 From: TheWhiteDog9487 Date: Tue, 11 Aug 2026 16:28:49 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E5=BD=93=E6=9D=83=E9=99=90=E4=B8=8D?= =?UTF-8?q?=E8=B6=B3=E6=97=B6=EF=BC=8C=E8=87=AA=E5=8A=A8=E4=BD=BF=E7=94=A8?= =?UTF-8?q?sudo=E9=87=8D=E5=90=AF=E8=87=AA=E8=BA=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 2 +- README.md | 21 ++++++++++++--------- language.cs | 12 ++++++++++-- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d01fd3..85f003f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,7 +32,7 @@ jobs: alpine:latest /bin/sh -c ' apk update apk add build-base dotnet10-sdk clang - dotnet publish language.cs ' + dotnet publish language.cs /t:Rebuild --disable-build-servers --force ' - name: 重命名 if: ${{ matrix.runner == 'ubuntu-26.04-arm' }} run: sudo mv artifacts/language/language artifacts/language/language_arm diff --git a/README.md b/README.md index ef086f6..b875a08 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ## 支持的系统 - Debian +- Armbian - Ubuntu - Arch Linux - CachyOS @@ -44,25 +45,27 @@ rm language_arm 故此,如果您在使用过程中遇到问题,请在GitHub仓库打开一个新的issue,我会尽力处理 ## 如果你想自行编译 -最低依赖项: -- .NET 10 SDK -- 任意C++编译器 - -推荐依赖项: -- Alpine Linux +所需依赖项: - .NET 10 SDK - Clang -- build-base +- build-base或其他等效工具集 -推荐使用AlpineLinux进行编译,因为Alpine的系统libc就是musl,编译出的产物可以直接用而不需要管目标系统glibc的版本问题 +推荐使用Alpine Linux进行编译,因为Alpine的系统libc就是musl,编译出的产物可以直接用而不需要管目标系统glibc的版本问题 您可以使用下面的Docker命令获得一个Alpine环境 ```shell docker run --rm -it -v .:/src -w /src alpine ``` +如果您位于中国大陆境内,推荐先对apk进行换源,以加速软件包下载 +```shell +# https://help.mirrors.cernet.edu.cn/alpine/ +printf '%s' 'https://mirrors.cernet.edu.cn/alpine/latest-stable/main +https://mirrors.cernet.edu.cn/alpine/latest-stable/community +' | tee /etc/apk/repositories +``` 安装依赖项 ```shell apk update -apk add clang build-base dotnet10-sdk +apk add --no-cache clang build-base dotnet10-sdk ``` 然后进行编译 ```shell diff --git a/language.cs b/language.cs index bb2b049..0fef0bd 100644 --- a/language.cs +++ b/language.cs @@ -79,8 +79,16 @@ if (Enum.TryParse(OsDescription.Split(' ')[0], out 如果是误报,请在GitHub仓库打开一个新的issue。 ".Trim(); throw new NotSupportedException(Message); } } -if (Environment.IsPrivilegedProcess == false){ - throw new UnauthorizedAccessException("更改语言文件需要root权限,请使用sudo重新运行本程序"); } +if (Environment.IsPrivilegedProcess == false) { + using var Process = new Process(); + Process.StartInfo.FileName = "sudo"; + Process.StartInfo.ArgumentList.Add(Environment.ProcessPath ?? throw new Exception("无法获取当前程序路径")); + Console.WriteLine("更改语言文件需要root权限,当前用户权限不足"); + Console.WriteLine("正在尝试使用sudo重新运行程序"); + Console.WriteLine("如果您当前登录的用户拥有密码,请在sudo提示符中输入密码"); + Process.Start(); + Process.WaitForExit(); + Environment.Exit(Process.ExitCode); } Console.WriteLine($"探测到当前系统为 {OsDescription}"); switch (CurrentSystem){