Skip to content

Commit

Permalink
feat: Add add PhoneResource.h to WinUI resource extractor
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Jan 9, 2024
1 parent f63dc65 commit d90d888
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 202 deletions.
265 changes: 137 additions & 128 deletions tools/ResourcesExtractor/ResourcesExtractor/Magic.cs
Original file line number Diff line number Diff line change
@@ -1,148 +1,157 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ResourcesExtractor;

public static class Magic
{
public enum Languages
{
af_ZA = 0x0436,
am_et = 0x045e,
ar_SA = 0x401,
as_IN = 0x044d,
az_Latn_AZ = 0x42c,
bg_BG = 0x0402,
bn_IN = 0x445,
bs_Latn_BA = 0x141a,
ca_ES = 0x0403,
ca_Es_VALENCIA = 0x0803,
cs_CZ = 0x0405,
cy_GB = 0x0452,
da_DK = 0x0406,
de_DE = 0x407,
el_GR = 0x408,
en_GB = 0x809,
en_us = 0x409,
//es_ES = 0x40a,
es_MX = 0x80a,
et_EE = 0x0425,
eu_ES = 0x042d,
fa_IR = 0x0429,
fi_FI = 0x040b,
fil_ph = 0x0464,
fr_CA = 0xc0c,
fr_FR = 0x40c,
ga_IE = 0x83c,
gd_gb = 0x0491,
gl_ES = 0x0456,
gu_IN = 0x0447,
he_IL = 0x040d,
hi_IN = 0x0439,
hr_HR = 0x041a,
hu_HU = 0x040e,
hy_AM = 0x042b,
id_ID = 0x0421,
is_IS = 0x040f,
it_IT = 0x410,
ja_JP = 0x0411,
ka_GE = 0x0437,
kk_KZ = 0x043f,
km_kh = 0x0453,
kn_in = 0x044b,
ko_KR = 0x412,
kok_IN = 0x0457,
lb_LU = 0x046e,
lo_la = 0x0454,
lt_LT = 0x427,
lv_LV = 0x0426,
mi_NZ = 0x0481,
mk_mk = 0x042f,
ml_in = 0x044c,
mr_IN = 0x044e,
ms_MY = 0x43e,
mt_MT = 0x043a,
nb_NO = 0x414,
ne_NP = 0x0461,
nl_NL = 0x413,
nn_NO = 0x814,
or_IN = 0x0448,
pa_IN = 0x0446,
pl_PL = 0x0415,
pt_BR = 0x416,
pt_PT = 0x816,
quz_PE = 0xc6b,
ro_RO = 0x0418,
ru_RU = 0x0419,
sk_SK = 0x041b,
sl_SI = 0x0424,
sq_AL = 0x041c,
sr_Cyrl_BA = 0x1c1a,
sr_Cyrl_RS = 0x281a,
sr_Latn_RS = 0x241a,
sv_SE = 0x41d,
ta_in = 0x449,
te_in = 0x044a,
th_TH = 0x041e,
tr_TR = 0x041f,
tt_RU = 0x0444,
ug_CN = 0x0480,
uk_UA = 0x0422,
ur_PK = 0x420,
uz_latn_uz = 0x443,
vi_VN = 0x042a,
zh_CN = 0x0804,
zh_TW = 0x0404,
}
public enum Languages
{
af_ZA = 0x0436,
am_et = 0x045e,
ar_SA = 0x401,
as_IN = 0x044d,
az_Latn_AZ = 0x42c,
bg_BG = 0x0402,
bn_IN = 0x445,
bs_Latn_BA = 0x141a,
ca_ES = 0x0403,
ca_Es_VALENCIA = 0x0803,
cs_CZ = 0x0405,
cy_GB = 0x0452,
da_DK = 0x0406,
de_DE = 0x407,
el_GR = 0x408,
en_GB = 0x809,
en_us = 0x409,
//es_ES = 0x40a,
es_MX = 0x80a,
et_EE = 0x0425,
eu_ES = 0x042d,
fa_IR = 0x0429,
fi_FI = 0x040b,
fil_ph = 0x0464,
fr_CA = 0xc0c,
fr_FR = 0x40c,
ga_IE = 0x83c,
gd_gb = 0x0491,
gl_ES = 0x0456,
gu_IN = 0x0447,
he_IL = 0x040d,
hi_IN = 0x0439,
hr_HR = 0x041a,
hu_HU = 0x040e,
hy_AM = 0x042b,
id_ID = 0x0421,
is_IS = 0x040f,
it_IT = 0x410,
ja_JP = 0x0411,
ka_GE = 0x0437,
kk_KZ = 0x043f,
km_kh = 0x0453,
kn_in = 0x044b,
ko_KR = 0x412,
kok_IN = 0x0457,
lb_LU = 0x046e,
lo_la = 0x0454,
lt_LT = 0x427,
lv_LV = 0x0426,
mi_NZ = 0x0481,
mk_mk = 0x042f,
ml_in = 0x044c,
mr_IN = 0x044e,
ms_MY = 0x43e,
mt_MT = 0x043a,
nb_NO = 0x414,
ne_NP = 0x0461,
nl_NL = 0x413,
nn_NO = 0x814,
or_IN = 0x0448,
pa_IN = 0x0446,
pl_PL = 0x0415,
pt_BR = 0x416,
pt_PT = 0x816,
quz_PE = 0xc6b,
ro_RO = 0x0418,
ru_RU = 0x0419,
sk_SK = 0x041b,
sl_SI = 0x0424,
sq_AL = 0x041c,
sr_Cyrl_BA = 0x1c1a,
sr_Cyrl_RS = 0x281a,
sr_Latn_RS = 0x241a,
sv_SE = 0x41d,
ta_in = 0x449,
te_in = 0x044a,
th_TH = 0x041e,
tr_TR = 0x041f,
tt_RU = 0x0444,
ug_CN = 0x0480,
uk_UA = 0x0422,
ur_PK = 0x420,
uz_latn_uz = 0x443,
vi_VN = 0x042a,
zh_CN = 0x0804,
zh_TW = 0x0404,
}

public static unsafe string GetLocalizedResource(int resourceId, int langid)
{
IntPtr block = MAKEINTRESOURCEW(resourceId / 16 + 1);
int offset = resourceId % 16;
IntPtr hModule = NativeMethods.GetModuleHandle("Microsoft/* UWP don't rename */.UI.Xaml.dll");
public static unsafe string GetLocalizedResource(int resourceId, int langid)
{
try
{
IntPtr block = MAKEINTRESOURCEW(resourceId / 16 + 1);
int offset = resourceId % 16;
IntPtr hModule = NativeMethods.GetModuleHandle("Microsoft.UI.Xaml.dll");


// Find and load the string resource
//var langid = MAKELANGID(0x09 /* LANG_ENGLISH */, 0x01 /* SUBLANG_ENGLISH_US */);
IntPtr hResource = NativeMethods.FindResourceEx(hModule, (IntPtr)NativeMethods.RT_STRING, block, langid);
IntPtr hStr = NativeMethods.LoadResource(hModule, hResource);
// Find and load the string resource
//var langid = MAKELANGID(0x09 /* LANG_ENGLISH */, 0x01 /* SUBLANG_ENGLISH_US */);
IntPtr hResource = NativeMethods.FindResourceEx(hModule, (IntPtr)NativeMethods.RT_STRING, block, langid);
IntPtr hStr = NativeMethods.LoadResource(hModule, hResource);

ushort* curr = (ushort*)hStr;
for (int i = 0; i < offset; i++)
{
// Skip to next string
curr += (*curr + 1);
}
ushort* curr = (ushort*)hStr;
for (int i = 0; i < offset; i++)
{
// Skip to next string
curr += (*curr + 1);
}

int len = *curr;
curr++;
int len = *curr;
curr++;

return new string((char*)curr, 0, len).Replace("\u200f", "");
}
return new string((char*)curr, 0, len).Replace("\u200f", "");
}
catch (Exception)
{
Debug.WriteLine("Localization for " + resourceId + " is not available");
return null;
}
}

private static IntPtr MAKEINTRESOURCEW(int i)
{
ushort w = unchecked((ushort)i);
IntPtr ip = (IntPtr)w;
return ip;
}
private static IntPtr MAKEINTRESOURCEW(int i)
{
ushort w = unchecked((ushort)i);
IntPtr ip = (IntPtr)w;
return ip;
}

//private static int MAKELANGID(int primaryLang, int subLang)
//{
// return ((((ushort)(subLang)) << 10) | (ushort)(primaryLang));
//}
//private static int MAKELANGID(int primaryLang, int subLang)
//{
// return ((((ushort)(subLang)) << 10) | (ushort)(primaryLang));
//}

private static class NativeMethods
{
public const int RT_STRING = 6;
private static class NativeMethods
{
public const int RT_STRING = 6;

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindResourceEx(IntPtr hModule, IntPtr lpType, IntPtr lpName, int wLanguage);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindResourceEx(IntPtr hModule, IntPtr lpType, IntPtr lpName, int wLanguage);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
}
}
90 changes: 51 additions & 39 deletions tools/ResourcesExtractor/ResourcesExtractor/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft/* UWP don't rename */.UI.Xaml;
Expand All @@ -8,49 +9,60 @@ namespace ResourcesExtractor;

public sealed partial class MainWindow : Window
{
private static List<(string ResourceName, int ResourceId)> GetResources()
{
var lines = File.ReadAllLines("C:\\Users\\PC\\Downloads\\microsoft-ui-xaml-winui3-release-1.4-stable\\microsoft-ui-xaml-winui3-release-1.4-stable\\dxaml\\xcp\\inc\\localizedResource.h");
var resources = new List<(string ResourceName, int ResourceId)>();
foreach (var line in lines)
{
if (line.StartsWith("#define"))
{
var match = Regex.Match(line, @"#define (.+?)\s+(\d+)");
var resourceName = match.Groups[1].Value;
var resourceId = int.Parse(match.Groups[2].Value);
resources.Add((resourceName, resourceId));
}
}

return resources;
}

public MainWindow()
{
this.InitializeComponent();

var resources = GetResources();
foreach (var lang in Enum.GetValues<Magic.Languages>())
{
var filePath = $"C:\\GeneratedResources\\{lang.ToString().Replace('_', '-')}\\Resources.resw";
var directory = Path.GetDirectoryName(filePath);
Directory.CreateDirectory(directory);
var writer = new StreamWriter(new FileStream(filePath, FileMode.CreateNew));
writer.Write(Constants.ReswFileStart);
foreach (var resource in resources)
{
string resourceValue = Magic.GetLocalizedResource(resource.ResourceId, (int)lang);
writer.Write($"""
private static List<(string ResourceName, int ResourceId)> GetResources()
{
var allResources = new List<(string ResourceName, int ResourceId)>();
allResources.AddRange(GetResourcesFromFile("dxaml\\phone\\lib\\PhoneResource.h"));
allResources.AddRange(GetResourcesFromFile("dxaml\\xcp\\inc\\localizedResource.h"));
return allResources;
}

private static List<(string ResourceName, int ResourceId)> GetResourcesFromFile(string relativePath)
{
var lines = File.ReadAllLines($"C:\\Dev\\microsoft-ui-xaml\\{relativePath}");
var resources = new List<(string ResourceName, int ResourceId)>();
foreach (var line in lines)
{
if (line.StartsWith("#define"))
{
var match = Regex.Match(line, @"#define (.+?)\s+(\d+)");
var resourceName = match.Groups[1].Value;
var resourceId = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
resources.Add((resourceName, resourceId));
}
}

return resources;
}

public MainWindow()
{
this.InitializeComponent();

var resources = GetResources();
foreach (var lang in Enum.GetValues<Magic.Languages>())
{
var filePath = $"C:\\GeneratedResources\\{lang.ToString().Replace('_', '-')}\\Resources.resw";
var directory = Path.GetDirectoryName(filePath);
Directory.CreateDirectory(directory);
var writer = new StreamWriter(new FileStream(filePath, FileMode.CreateNew));
writer.Write(Constants.ReswFileStart);
foreach (var resource in resources)
{
string resourceValue = Magic.GetLocalizedResource(resource.ResourceId, (int)lang);
if (resourceValue != null)
{
writer.Write($"""
<data name="{resource.ResourceName}" xml:space="preserve">
<value>{resourceValue}</value>
</data>

""");
}
}
}

writer.Write(Constants.ReswFileEnd);
writer.Close();
}
}
writer.Write(Constants.ReswFileEnd);
writer.Close();
}
}
}
Loading

0 comments on commit d90d888

Please sign in to comment.