diff --git a/scripts/generate_update_glyph_ranges.py b/scripts/generate_update_glyph_ranges.py new file mode 100644 index 000000000..6197c31c5 --- /dev/null +++ b/scripts/generate_update_glyph_ranges.py @@ -0,0 +1,44 @@ +import sys +import os +import re +import xml.etree.ElementTree as ET + +src_file = "src/duckstation-qt/qthost.cpp" +root_dir = os.path.join(os.path.dirname(__file__), "..") +src_path = os.path.join(root_dir, src_file) + +def parse_xml(path): + translations = "" + tree = ET.parse(path) + root = tree.getroot() + for node in root.findall("context/message/translation"): + if node.text: + translations += node.text + + chars = list(set([ord(ch) for ch in translations if ord(ch) >= 0x2000])) + chars.sort() + chars = "".join([chr(ch) for ch in chars]) + return chars + +def update_src_file(ts_file, chars): + ts_name = os.path.basename(ts_file) + pattern = re.compile(u'(// auto update.*' + ts_name + '.*\n[^"]+")[^"]*(".*)') + with open(src_path) as f: + original = f.read() + update = pattern.sub(u'\\1' + chars + '\\2', original) + if original != update: + with open(src_path, 'w') as f: + f.write(update) + print("updated " + src_file) + else: + print("no need to update " + src_file) + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("usage: %s " % sys.argv[0]) + sys.exit(1) + + chars = parse_xml(sys.argv[1]) + print (chars) + print ("%d character(s) detected." % len(chars)) + update_src_file(sys.argv[1], chars) diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 07daa5f29..1050149bb 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -89,6 +89,8 @@ static void SetDataDirectory(); static bool SetCriticalFolders(); static void SetDefaultSettings(SettingsInterface& si, bool system, bool controller); static void SaveSettings(); +static const ImWchar* GetGlyphRangesJapanese(); +static const ImWchar* GetGlyphRangesChinese(); static void InstallTranslator(); static std::string GetFontPath(const char* name); static void InitializeEarlyConsole(); @@ -437,6 +439,46 @@ static std::string QtHost::GetFontPath(const char* name) #endif } +static const ImWchar* QtHost::GetGlyphRangesJapanese() +{ + // auto update by generate_update_glyph_ranges.py with duckstation-qt_ja.ts + static const char16_t chars[] = u"―←↑→↓□△○ 、。々「」〜あいうえおかがきぎくぐけげこごさざしじすずせそぞただちっつづてでとどなにぬねのはばびへべほぼぽまみむめもやゆよらりるれろわをんァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソタダチッツテデトドナニネノハバパヒビピフブプヘベペホボポマミムメモャュユョヨラリルレロワンー一上下不与両並中主了予事二互交人介他付代令以件任休伸位低体作使例供依係保信修個倍値停傍備像優元先光入全公共具典内再凍処出分切初別利到制削前割力功加効動勧化十協単去参及収取可右号各合同名向含告周呼命問善回囲固圧在地垂型埋域基報場境増壊声売変外多大失奨好妥始子字存学安完定宛実密対射小少岐左差己巻帰常幅年度座延式引弱張強当形影役待後従得御復微心必忘応性恐情意態成戻所手扱抑投択押拡持指振挿排探接推描提換損摩撃撮操改敗数整文料断新方既日早明映時景更書替最有期未本来析枚果栄検構標権機次止正歪毎比永求決況法波注消深混済減測源準滑演点無照牲特犠状獲率現理生用申画界番異疑発登的目直相瞬知短破確示禁秒称移種穴空立端符等算管範簡粋精約純索細終組経結統続維緑線編縮績置翻者耗背能自致般良色行表装補製複要見規視覧観解言計記設許訳証試詳認語説読調識警護象販責費質赤起超跡転軸軽較込近追送逆通速連進遅遊過達遠適遷選部重野量録長閉開間関防降限除隅隠集離電青非面音響頂項順領頭頻頼題類飛高鮮黒%?X"; + const int chars_length = sizeof(chars) / sizeof(chars[0]); + + static ImWchar base_ranges[] = + { + 0x0020, 0x007E, // Basic Latin + }; + const int base_length = sizeof(base_ranges) / sizeof(base_ranges[0]); + + static ImWchar full_ranges[base_length + chars_length * 2 + 1] = {0}; + memcpy(full_ranges, base_ranges, sizeof(base_ranges)); + for (int i = 0; i < chars_length; i++) { + full_ranges[base_length + i * 2] = full_ranges[base_length + i * 2 + 1] = chars[i]; + } + return full_ranges; +} + +static const ImWchar* QtHost::GetGlyphRangesChinese() +{ + // auto update by generate_update_glyph_ranges.py with duckstation-qt_zh-cn.ts + static const char16_t chars[] = u"“”…、。一丁三上下不与且丢两个中临为主么义之乐也了予事二于互亚些交亦产享人仅介从他代令以们件价任份仿休优会传伸但位低住体何余作你佳使例供依侧便保信修倍倒候值假偏停储像允充先光免入全公六共关其具典兼内册再写冲决况冻准减几出击函分切列则创初删利别到制刷前剔剩剪力功加务动助勾包化匹区十升半协卓单南占卡即卸压原去参叉及双反发取受变口只可台右号各合同名后向吗否含听启呈告周和哈响哪商善喜器噪回因围固国图圆圈在地场址坏坐块垂型域基堆填境增声处备复外多夜够大太失头夹奏好如始媒子孔字存它守安完宏官定实宫家容宽寄密察寸对寻导封射将小少尚尝尤就尺尼尽尾局层屏展属峰崩工左差已希带帧帮常幕平年并序库应底度延建开异弃式引张弦弱弹强当录形彩影彻征径很得心必忆志快忽态性总恢息您悬情想意慢懂戏成我或战截户所扇手才打执扩扫扭扳批找把抓投抖折护报抱抹拉拟择拷拿持指按挎挑振损换据捷排接控推描提插握搜携摇撤播操支收改放故效敏数整文斗料断新方施无日旦旧旨时明易星映是显景暂暗曲更替最有服望期未末本机权杆束条来板构析果枪某染查标栈栏校样核根格案档梦梳检概榜槽模横次欢欧欲歉止正此步死段每比毫水求汇池没法波注洲活派流浅测浏消涡深混添清渐渡渲游溃源滑滚滞滤澳激灰灵点炼热焦然照爆片版牌牙物特状独率玩环现理瑕生用由电画畅界留略疵登百的监盒盖盘目直相看真眠着瞬知矫码破硬确碎碰磁示禁离种秒称移程稍稳空突窗立站端笔第等筛签简算管类精系素索红约级纯纵纹线组细终经绑结绘给络统继绩续维绿缓编缘缩网置美翻者而耐耗联背能脑自致般色节若范荐荷获菜著蓝藏行补表衷被裁裂装要覆见观规视览觉角解触言警计订认议记许论设访证识译试该详语误说请读调象贝负败账质贴费资赖起超越足跃距跟跨路跳踪身轨转轮软轴载较辑输辨边达过运近返还这进远连迟述追退送适逆选透通速造遇道遵那邻部都配醒采释里重野量金针钮链锁锐错键锯镜长闭问间阈防阻降限除险隐隔障难集需震静非靠面音页顶项顺须顿预频题颜额风驱验高黑默鼠齿,:?"; + const int chars_length = sizeof(chars) / sizeof(chars[0]); + + static ImWchar base_ranges[] = + { + 0x0020, 0x007E, // Basic Latin + }; + const int base_length = sizeof(base_ranges) / sizeof(base_ranges[0]); + + static ImWchar full_ranges[base_length + chars_length * 2 + 1] = { 0 }; + memcpy(full_ranges, base_ranges, sizeof(base_ranges)); + for (int i = 0; i < chars_length; i++) { + full_ranges[base_length + i * 2] = full_ranges[base_length + i * 2 + 1] = chars[i]; + } + return full_ranges; +} + void QtHost::InstallTranslator() { const QString language(QString::fromStdString(Host::GetBaseStringSettingValue("Main", "Language", "en"))); @@ -488,12 +530,12 @@ void QtHost::InstallTranslator() if (language == QStringLiteral("ja")) { ImGuiManager::SetFontPath(GetFontPath("msgothic.ttc")); - ImGuiManager::SetFontRange(ImGui::GetIO().Fonts->GetGlyphRangesJapanese()); + ImGuiManager::SetFontRange(GetGlyphRangesJapanese()); } else if (language == QStringLiteral("zh-cn")) { ImGuiManager::SetFontPath(GetFontPath("msyh.ttc")); - ImGuiManager::SetFontRange(ImGui::GetIO().Fonts->GetGlyphRangesChineseSimplifiedCommon()); + ImGuiManager::SetFontRange(GetGlyphRangesChinese()); } #endif } diff --git a/src/frontend-common/achievements.cpp b/src/frontend-common/achievements.cpp index db7294d12..6c05211f9 100644 --- a/src/frontend-common/achievements.cpp +++ b/src/frontend-common/achievements.cpp @@ -558,8 +558,9 @@ void Achievements::SetChallengeMode(bool enabled) if (HasActiveGame()) { Host::AddKeyedOSDMessage("achievements_set_challenge_mode", - Host::TranslateStdString("Achievements", enabled ? "Hardcore mode is now enabled." : - "Hardcore mode is now disabled."), + enabled ? + Host::TranslateStdString("Achievements", "Hardcore mode is now enabled.") : + Host::TranslateStdString("Achievements", "Hardcore mode is now disabled."), 10.0f); } diff --git a/src/frontend-common/imgui_manager.cpp b/src/frontend-common/imgui_manager.cpp index f5e427dff..99dc08981 100644 --- a/src/frontend-common/imgui_manager.cpp +++ b/src/frontend-common/imgui_manager.cpp @@ -30,7 +30,7 @@ static void SetStyle(); static void SetKeyMap(); static bool LoadFontData(); static bool AddImGuiFonts(bool fullscreen_fonts); -static ImFont* AddTextFont(float size, bool full_range); +static ImFont* AddTextFont(float size); static ImFont* AddFixedFont(float size); static bool AddIconFonts(float size); static void AcquirePendingOSDMessages(); @@ -419,7 +419,7 @@ bool ImGuiManager::LoadFontData() return true; } -ImFont* ImGuiManager::AddTextFont(float size, bool full_range) +ImFont* ImGuiManager::AddTextFont(float size) { static const ImWchar default_ranges[] = { // Basic Latin + Latin Supplement + Central European diacritics @@ -445,7 +445,7 @@ ImFont* ImGuiManager::AddTextFont(float size, bool full_range) cfg.FontDataOwnedByAtlas = false; return ImGui::GetIO().Fonts->AddFontFromMemoryTTF(s_standard_font_data.data(), static_cast(s_standard_font_data.size()), size, &cfg, - (s_font_range && full_range) ? s_font_range : default_ranges); + s_font_range ? s_font_range : default_ranges); } ImFont* ImGuiManager::AddFixedFont(float size) @@ -478,7 +478,7 @@ bool ImGuiManager::AddImGuiFonts(bool fullscreen_fonts) ImGuiIO& io = ImGui::GetIO(); io.Fonts->Clear(); - s_standard_font = AddTextFont(standard_font_size, true); + s_standard_font = AddTextFont(standard_font_size); if (!s_standard_font || !AddIconFonts(standard_font_size)) return false; @@ -488,14 +488,13 @@ bool ImGuiManager::AddImGuiFonts(bool fullscreen_fonts) if (fullscreen_fonts) { - // Don't add full range for FSUI, we probably don't have the texture space, and it's not translated yet anyway. const float medium_font_size = std::ceil(ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_MEDIUM_FONT_SIZE)); - s_medium_font = AddTextFont(medium_font_size, false); + s_medium_font = AddTextFont(medium_font_size); if (!s_medium_font || !AddIconFonts(medium_font_size)) return false; const float large_font_size = std::ceil(ImGuiFullscreen::LayoutScale(ImGuiFullscreen::LAYOUT_LARGE_FONT_SIZE)); - s_large_font = AddTextFont(large_font_size, false); + s_large_font = AddTextFont(large_font_size); if (!s_large_font || !AddIconFonts(large_font_size)) return false; }