{"id":417,"date":"2024-10-11T20:25:26","date_gmt":"2024-10-12T01:25:26","guid":{"rendered":"https:\/\/www.dphrygian.com\/wordpress\/?p=417"},"modified":"2024-10-11T21:08:32","modified_gmt":"2024-10-12T02:08:32","slug":"devs-journal-11-oct-2024","status":"publish","type":"post","link":"https:\/\/www.dphrygian.com\/wordpress\/?p=417","title":{"rendered":"Dev&#8217;s Journal &#8211; 11 Oct 2024"},"content":{"rendered":"\n<p>When I shipped <em>Eldritch<\/em> back in 2013, indie games were in a different place. Localization wasn&#8217;t expected, so I didn&#8217;t do it; and when people volunteered to do translations, I accepted them and hastily assembled a localization system in my engine. But I never felt good about people working on my game for free, and I simply decided to not localize my subsequent games at all.<\/p>\n\n\n\n<p>I don&#8217;t know yet if I&#8217;ll localize <em>Eldritch 2<\/em>; I want to, but I want to do it right this time and pay for the service, and that can be expensive. But regardless of whether I can afford it, there was a big lingering tech issue that I&#8217;d been ignoring for a decade, which I needed to solve before approaching localization services. I&#8217;d never had CJK (Chinese, Japanese, and Korean) support in my engine.<\/p>\n\n\n\n<p>Back in the <em>Eldritch<\/em> days, I used some fonts that only included the Latin alphabet. Then I needed to support Russian and Ukrainian translations, so I hacked in some alternate font sheets with the Cyrillic alphabet. Then someone sent me a Georgian translation so I added another font sheet for Georgian. And that all worked fine, because those are all alphabet scripts. But Chinese, Japanese, and Korean scripts have thousands of characters, and rendering out a font sheet with every one of those character isn&#8217;t possible.<\/p>\n\n\n\n<p>There are a few common solutions to this problem, but the one that I think fits the best for my games is to use the translated string table as a source for which characters must be included. Out of thousands of possible characters, a particular game may only use hundreds, and there is no need to include the rest. (This assumption only holds if users cannot input arbitrary text; that&#8217;s true in my games.)<\/p>\n\n\n\n<p>So I spent today tackling that problem. There were a number of related issues I needed to solve, especially around unified ideographs (where different CJK scripts render the same Unicode codepoint differently, corresponding to the display language). And then I needed some translated strings, so I wrote up some tools code to export a string table that I could machine translate with AWS. (To be clear, I will not be using machine translation for the real game, this is <em>only<\/em> to give me something to work with!)<\/p>\n\n\n\n<p>And here we are! Please ignore the machine translations, I know they&#8217;re very wrong. And please understand this is not a list of the intended languages; some might be added, some might be removed. And there&#8217;s some remaining work to do like localizing keyboard keys. But the point is, my engine can now finally display CJK characters, in their language-appropriate variants.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1024x593.png\" alt=\"\" class=\"wp-image-418\" srcset=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1024x593.png 1024w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-300x174.png 300w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-768x444.png 768w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1536x889.png 1536w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1200x694.png 1200w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1-1024x593.png\" alt=\"\" class=\"wp-image-419\" srcset=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1-1024x593.png 1024w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1-300x174.png 300w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1-768x444.png 768w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1-1536x889.png 1536w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1-1200x694.png 1200w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-1.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2-1024x593.png\" alt=\"\" class=\"wp-image-420\" srcset=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2-1024x593.png 1024w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2-300x174.png 300w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2-768x444.png 768w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2-1536x889.png 1536w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2-1200x694.png 1200w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-2.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3-1024x593.png\" alt=\"\" class=\"wp-image-421\" srcset=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3-1024x593.png 1024w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3-300x174.png 300w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3-768x444.png 768w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3-1536x889.png 1536w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3-1200x694.png 1200w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-3.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4-1024x593.png\" alt=\"\" class=\"wp-image-422\" srcset=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4-1024x593.png 1024w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4-300x174.png 300w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4-768x444.png 768w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4-1536x889.png 1536w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4-1200x694.png 1200w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-4.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5-1024x593.png\" alt=\"\" class=\"wp-image-423\" srcset=\"https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5-1024x593.png 1024w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5-300x174.png 300w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5-768x444.png 768w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5-1536x889.png 1536w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5-1200x694.png 1200w, https:\/\/www.dphrygian.com\/wordpress\/wp-content\/uploads\/2024\/10\/image-5.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>When I shipped Eldritch back in 2013, indie games were in a different place. Localization wasn&#8217;t expected, so I didn&#8217;t do it; and when people volunteered to do translations, I accepted them and hastily assembled a localization system in my engine. But I never felt good about people working on my game for free, and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-417","post","type-post","status-publish","format-standard","hentry","category-eldritch-2"],"_links":{"self":[{"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/417"}],"collection":[{"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=417"}],"version-history":[{"count":2,"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/417\/revisions"}],"predecessor-version":[{"id":425,"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/417\/revisions\/425"}],"wp:attachment":[{"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=417"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=417"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dphrygian.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=417"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}