mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-06-20 14:10:59 +10:00
Update reader.
This commit is contained in:
+177
-16
@@ -1,29 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
public const int LOCALE_SSHORTESTSCRIPT = 0x0000004F; // 获取四字母脚本代码
|
||||
public const uint KLF_ACTIVATE = 0x00000001; // 激活键盘布局
|
||||
// GetLocaleInfoW for LCID-based queries
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int GetLocaleInfoW (int Locale, int LCType, [Out] StringBuilder lpLCData, int cchData);
|
||||
|
||||
// GetLocaleInfoEx for locale name based queries
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int GetLocaleInfoEx (string lpLocaleName, int LCType, [Out] StringBuilder lpLCData, int cchData);
|
||||
|
||||
// LocaleNameToLCID - available on Vista+; fallback is to use CultureInfo
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int LocaleNameToLCID (string lpName, uint dwFlags);
|
||||
|
||||
// LCIDToLocaleName (Vista+)
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int LCIDToLocaleName (int Locale, [Out] StringBuilder lpName, int cchName, uint dwFlags);
|
||||
[DllImport ("user32.dll")]
|
||||
public static extern IntPtr GetKeyboardLayout (uint dwLayout);
|
||||
[DllImport ("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr LoadKeyboardLayout (string pwszKLID, uint Flags);
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Language: System.Globalization.CultureInfo
|
||||
{
|
||||
public _I_Language (string localeName) : base (localeName) { }
|
||||
public string AbbreviatedName => this.ThreeLetterISOLanguageName;
|
||||
public string LanguageTag => this.IetfLanguageTag ?? this.Name;
|
||||
public int LayoutDirection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (base.TextInfo.IsRightToLeft) return 1;
|
||||
string tag = this.LanguageTag;
|
||||
bool isVerticalCandidate = false;
|
||||
if (tag != null)
|
||||
{
|
||||
var scriptMatch = Regex.Match (tag, @"-([A-Za-z]{4})(?:-|$)");
|
||||
if (scriptMatch.Success)
|
||||
{
|
||||
string script = scriptMatch.Groups [1].Value;
|
||||
if (script == "Hani" || script == "Hira" || script == "Kana" || script == "Jpan" || script == "Kore" || script == "Hans" || script == "Hant")
|
||||
isVerticalCandidate = true;
|
||||
}
|
||||
if (!isVerticalCandidate)
|
||||
{
|
||||
var regionMatch = Regex.Match (tag, @"-([A-Za-z]{2})$");
|
||||
if (regionMatch.Success)
|
||||
{
|
||||
string region = regionMatch.Groups [1].Value.ToUpperInvariant ();
|
||||
if (region == "JP" || region == "CN" || region == "TW" || region == "HK" || region == "MO" || region == "KR")
|
||||
isVerticalCandidate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isVerticalCandidate)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public string Script
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder (10);
|
||||
if (NativeMethods.GetLocaleInfoEx (this.Name, NativeMethods.LOCALE_SSHORTESTSCRIPT, sb, sb.Capacity) > 0)
|
||||
return sb.ToString ();
|
||||
|
||||
// 如果失败,尝试从语言标记中解析脚本子标记(如 "zh-Hans-CN" 中的 "Hans")
|
||||
var match = Regex.Match (this.Name, @"-([A-Za-z]{4})(?:-|$)");
|
||||
if (match.Success)
|
||||
return match.Groups [1].Value;
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
public _I_List GetExtensionSubtags (string singleton)
|
||||
{
|
||||
if (string.IsNullOrEmpty (singleton) || singleton.Length != 1)
|
||||
throw new ArgumentException ("Singleton must be a single character", nameof (singleton));
|
||||
var subtags = new List<string> ();
|
||||
string tag = this.LanguageTag;
|
||||
string pattern = $@"-{Regex.Escape (singleton)}-([a-zA-Z0-9](?:-[a-zA-Z0-9]+)*)";
|
||||
var match = Regex.Match (tag, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
string extPart = match.Groups [1].Value;
|
||||
subtags.AddRange (extPart.Split ('-'));
|
||||
}
|
||||
return new _I_List (subtags.Select (i => (object)i));
|
||||
}
|
||||
public bool TrySetInputMethodLanguageTag (string languageTag)
|
||||
{
|
||||
int lcid = NativeMethods.LocaleNameToLCID (languageTag, 0);
|
||||
if (lcid == 0)
|
||||
return false;
|
||||
string klid = $"{lcid:X8}";
|
||||
IntPtr hkl = NativeMethods.LoadKeyboardLayout (klid, NativeMethods.KLF_ACTIVATE);
|
||||
return hkl != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Locale
|
||||
@@ -47,7 +134,6 @@ namespace DataUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current LCID (int)
|
||||
public int CurrentLCID
|
||||
{
|
||||
@@ -63,7 +149,6 @@ namespace DataUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert LCID -> locale name (e.g. 1033 -> "en-US")
|
||||
public string ToLocaleName (int lcid)
|
||||
{
|
||||
@@ -87,7 +172,6 @@ namespace DataUtils
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Convert locale name -> LCID
|
||||
public int ToLCID (string localeName)
|
||||
{
|
||||
@@ -111,7 +195,6 @@ namespace DataUtils
|
||||
// fallback: invariant culture
|
||||
return CultureInfo.InvariantCulture.LCID;
|
||||
}
|
||||
|
||||
// Return a locale info string for given LCID and LCTYPE. LCTYPE is the Win32 LOCALE_* constant.
|
||||
// Returns a string (or empty string on failure).
|
||||
public object LocaleInfo (int lcid, int lctype)
|
||||
@@ -177,7 +260,6 @@ namespace DataUtils
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// LocaleInfoEx: query by locale name string and LCTYPE
|
||||
// Returns string if available; otherwise returns the integer result code (as int) if string empty (mimic C++ behavior).
|
||||
public object LocaleInfoEx (string localeName, int lctype)
|
||||
@@ -239,7 +321,6 @@ namespace DataUtils
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers similar to the C++: restricted (language) and elaborated (region) codes
|
||||
public string GetLocaleRestrictedCode (string localeName)
|
||||
{
|
||||
@@ -257,7 +338,6 @@ namespace DataUtils
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetLocaleElaboratedCode (string localeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (localeName)) localeName = CurrentLocale;
|
||||
@@ -284,7 +364,6 @@ namespace DataUtils
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// LCID -> combined code like "en-US" (with configurable separator)
|
||||
public string LcidToLocaleCode (int lcid)
|
||||
{
|
||||
@@ -304,7 +383,6 @@ namespace DataUtils
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Get the user default locale name
|
||||
public string GetUserDefaultLocaleName ()
|
||||
{
|
||||
@@ -317,7 +395,6 @@ namespace DataUtils
|
||||
catch { }
|
||||
return LcidToLocaleCode (CultureInfo.CurrentCulture.LCID);
|
||||
}
|
||||
|
||||
// Get system default locale name (machine)
|
||||
public string GetSystemDefaultLocaleName ()
|
||||
{
|
||||
@@ -330,7 +407,6 @@ namespace DataUtils
|
||||
catch { }
|
||||
return LcidToLocaleCode (CultureInfo.InstalledUICulture.LCID);
|
||||
}
|
||||
|
||||
// Get computer locale code similar to C++ approach
|
||||
public string GetComputerLocaleCode ()
|
||||
{
|
||||
@@ -350,7 +426,38 @@ namespace DataUtils
|
||||
// fallback to invariant
|
||||
return CultureInfo.InvariantCulture.Name ?? string.Empty;
|
||||
}
|
||||
|
||||
public _I_List RecommendLocaleNames
|
||||
{
|
||||
get
|
||||
{
|
||||
var arr = new string [] {
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture.Name,
|
||||
GetUserDefaultLocaleName (),
|
||||
GetSystemDefaultLocaleName (),
|
||||
LcidToLocaleCode (CurrentLCID),
|
||||
GetLocaleRestrictedCode (System.Threading.Thread.CurrentThread.CurrentCulture.Name),
|
||||
GetLocaleRestrictedCode (GetUserDefaultLocaleName ()),
|
||||
GetLocaleRestrictedCode (GetSystemDefaultLocaleName ()),
|
||||
"en-US",
|
||||
"en"
|
||||
};
|
||||
var list = new _I_List ();
|
||||
foreach (var loc in arr)
|
||||
{
|
||||
var lloc = loc.Trim ().ToLowerInvariant ();
|
||||
var isfind = false;
|
||||
foreach (var item in list)
|
||||
{
|
||||
var str = item as string;
|
||||
if (string.IsNullOrWhiteSpace (str)) isfind = true;
|
||||
isfind = str.Trim ().ToLowerInvariant () == lloc;
|
||||
if (isfind) break;
|
||||
}
|
||||
if (!isfind) list.Add (loc);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
// Compare two locale names; returns true if equal by name or LCID
|
||||
public bool LocaleNameCompare (string left, string right)
|
||||
{
|
||||
@@ -366,8 +473,62 @@ namespace DataUtils
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Constants
|
||||
private const int LOCALE_NAME_MAX_LENGTH = 85; // defined by Windows
|
||||
public _I_Language CreateLanguage (string localeName) => new _I_Language (localeName);
|
||||
public static string CurrentInputMethodLanguageTag
|
||||
{
|
||||
get
|
||||
{
|
||||
IntPtr hkl = NativeMethods.GetKeyboardLayout (0);
|
||||
int lcid = hkl.ToInt32 () & 0xFFFF;
|
||||
|
||||
StringBuilder sb = new StringBuilder (85);
|
||||
int result = NativeMethods.LCIDToLocaleName (lcid, sb, sb.Capacity, 0);
|
||||
if (result > 0)
|
||||
return sb.ToString ();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static bool IsWellFormed (string languageTag)
|
||||
{
|
||||
if (string.IsNullOrEmpty (languageTag))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var _ = new CultureInfo (languageTag);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static _I_List GetMuiCompatibleLanguageListFromLanguageTags (IEnumerable<string> languageTags)
|
||||
{
|
||||
var result = new List<string> ();
|
||||
foreach (string tag in languageTags)
|
||||
{
|
||||
if (string.IsNullOrEmpty (tag))
|
||||
continue;
|
||||
result.Add (tag);
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (tag);
|
||||
string parent = ci.Parent.Name;
|
||||
if (!string.IsNullOrEmpty (parent) && parent != tag && !result.Contains (parent))
|
||||
result.Add (parent);
|
||||
}
|
||||
catch { }
|
||||
string neutral = Regex.Replace (tag, @"-.*$", "");
|
||||
if (neutral != tag && !result.Contains (neutral))
|
||||
result.Add (neutral);
|
||||
}
|
||||
if (!result.Contains ("neutral"))
|
||||
result.Add ("neutral");
|
||||
return new _I_List (result.Select (t => (object)t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user