Making Scrabble Multilingual in C# with GitHub Collaboration

Have you ever wondered what it’d be like to play Scrabble in another language? Together with my teammates – Min Chua, Xingyue (Silver) Zhang, and Oussama Bel Aiba – we found a Scrabble C# project on GitHub and collaborated with our coding and internationalization skills to localize it into Japanese, French, and Chinese (Chinese had only the UI localized, however, as Scrabble cannot be played in languages without an alphabet).

As none of us had much programming experience coming into this project, we surprised ourselves by what we were able to accomplish by the end, and there were many small things we were able to self-teach ourselves along the way. See the diagram below for our general process! My main contributions were in the GitHub Setup, part of DTP, and Making the Board Multilingual steps.

Technology/Skills Used: GitHub, Visual Studio, WPF/XAML, C#, Phrase (formerly Memsource)

GitHub Setup

Our first task was to set up a GitHub environment that allowed us to collaborate on the code. We were all new to GitHub, but upon finding that it directly integrates with Visual Studio (our Integrated Development Environment), we connected our accounts and got up and running fairly quickly.

The convenient Git Changes panel directly letting us commit, push, and pull from Visual Studio

We worked primarily through making new branches whenever one of us wanted to try making any changes, and if we were successful, we’d merge our branch back with the master. Visual Studio offers a neat screen showing branch history:

With my teammate Silver, we took screenshots as we learned how to use these basic features and compiled them together in instructions that our team could use (as well as just for future use in general for similar projects):

Externalizing Strings

Now that we had our project set up for collaboration, we started the main process. In software that wasn’t developed with localization in mind, the first thing to fix is the hardcoded strings and concatenation that are inevitably present in the code, such as here:

In the actual game, this could manifest as something like “Player 1 gets R!” when the variables are filled in

For those who don’t know why this would be problematic – mini localization lesson! While this is fine for monolingual software, if the program needs to run in multiple languages, there’s a couple reasons this would fail:

  • No ability to display different strings depending on the language the user is playing in (while technically you could create “if” statements for each language, the code would quickly get unnecessarily long as more and more languages are added).
  • The concatenation makes the output based strictly on English sentence structures, allowing no flexibility for changed word orders in other languages. For example, the string in the above screenshot could read as “Player 1 gets R!” in the actual program, but it’s coded so that the “R” must come after the “gets”, whereas in Japanese, it would come before: プレーヤー1はRを取得した!

Both of these can be solved by externalizing the string to a resource file. These not only allow for easy translation of all the strings in a program in one go without having to manually pore through the code, but also allow flexibility in word order through injecting variables – see how the same line of code from above looked after it was externalized in our resource file, named “peau”:

Silver and Min took the lead on externalizing most strings into the resource file (Min noted some of the strings appeared in WPF files with XAML markup rather than C# and thus required a more involved externalization method – you can read her post here), with me and Oussama helping out with a few. We ended up with a resource file with around 100 strings in it, each labeled in the comment section with which file it appeared in for easy reference:

Language Switcher Creation

Making the language switcher (option for user to select a preferred language from a dropdown menu, upon which the UI text would change to that language) was unexpectedly difficult. If we had a Windows Form, we could’ve reinitialized the form (meaning: upon the user changing the language, trigger a command that loops through all elements in the window to change their language), but this approach didn’t work for the WPF .xaml file we had.

Min, however, came up with an ingenious idea to get around this, which Silver then implemented. You can see more details about it on Silver’s post here, but the solution was essentially adding a separate popup window for just the language picker before the first main screen, then loading everything else.

Translation and DTP

After we externalized all the strings, we took our English resource file and made a project in Phrase (formerly Memsource) to translate into our three target languages – me on Japanese, Oussama on French, and Min and Silver on Chinese. One difficulty we all encountered was lack of context when translating.

We’d tried to take steps to avoid this difficulty by putting comments on each string labeling which file in the project it appeared in, but even so, strings that were part of a concatenation structure initially such as “scores” or “This is a” were impossible to translate properly without going back and playing the game ourselves to see the context.

After getting through this text, we still had one small graphic on the main screen to localize, which Silver and Min took care of in Photoshop:

However, it was surprisingly hard to set things up so the logo that appeared in the program was for whichever language the user chose. As images can be stored in resource files, at first thought I could treat the image path like an externalized string and simply call the resource value key from the code, but this did not work in the WPF .xaml file we had. After a lot of searching online, I found this page that I was able to follow the instructions on to successfully set the image source with a string in the resource file containing the image path:

Making the Board Multilingual

Now that the UI was localized, our last major challenge was to make the actual tiles multilingual so the Scrabble gameplay itself could be played in other languages. I focused on doing this first in Japanese and went through a few different substeps to make it work:

Scrabble Wordlist

The first task was to incorporate a Japanese wordlist, as the way the program confirms if you’ve made a valid word is by checking it against a .txt file with every word in the English language:

Doing the Japanese version of this was actually quite difficult due to an important restriction: Scrabble is based on having a single alphabet, but Japanese is written in three different scripts (hiragana, katakana, and kanji). It’s possible to write everything in just one (hiragana), but the only Japanese dictionary file I could find had all three alphabets, as shown below. So, I ended up using regex find & replace expressions to a) take away all the markup language, and b) convert everything to a single script:

The Tiles

The next task was setting the tiles into Japanese. I noticed the original developer set up the English tiles through a for loop on a char starting at ‘A’ and ending at ‘Z’, which works because of how chars are stored as Unicode values in C#. Thus, I was able to do the same thing with Japanese and start the for loop at the first character in its alphabet and end it at the last character in its alphabet, then set the program to create the Japanese tiles if the user language was JA and create the English tiles if not:

And with that, we had Japanese tiles!

Side Note

For those who know Japanese: You might notice that the first letter is the small ぁ rather than the regular あ and find that odd. One consequence of converting everything to hiragana is that words normally written in katakana now need to be written in hiragana, so the small ぁ would be relevant for words like ファイル, which becomes ふぁいる in hiragana. Also, the Unicode block for hiragana notably does NOT contain the long vowel ‘ー’, so a for loop through hiragana does not cover it and ‘ー’ needed to be added as a tile separately (which you can see in the screenshot above).

Tile Frequencies/Points

As each letter in Scrabble has a) a specific number of tiles for it and b) a specific point value, these also needed to be set for Japanese. There unfortunately was no Japanese Scrabble game I could find to reference, but I was lucky enough to find a forum where someone had actually done the work of figuring out the appropriate frequency/point values, so I based the code off of that. Here is the section for setting the number of tiles for each letter in Japanese (top) and English (bottom) – you’ll notice that Japanese has quite a few more letters in its alphabet than English:

Blank Tile

Whenever users want to place a blank tile, there is a popup window asking which letter of the alphabet they want to use it for. I adapted this to the Japanese alphabet too, with essentially the same for loop method I used for creating the Japanese titles initially. It is worth noting the developer chose the dash ‘-‘ to represent the blank tile, but as this would be too easy to confuse with the Japanese long vowel ‘ー’, we decided to change it to an asterisk ‘*’:

With the Japanese Scrabble board ready to go, Silver took the step of doing the same for French – finding the French Scrabble wordlist, setting tile point values and frequencies, etc. For Chinese, it is impossible to make Scrabble work due to lack of an alphabet, so we only localized the UI for it and kept the tiles/words in English.

LQA (Linguistic Quality Assurance)

The last step was to see if there were any language-specific issues that would arise when a user played through the game and the strings appeared in-context. For example, a classic issue is that text will expand in length when translated into the target language, causing awkward truncation. This happened with the SWAP button for Japanese where it was too small for all of the Japanese translation to fit, so we adjusted the button sizes to be bigger:

Other times, a lack of context during translation caused us to translate something incorrectly, or we saw that the initial concatenation caused the sentence structure to be in the wrong order. Since we only found these problems during playtesting, a lot of little changes had to be made during this step, usually referred to as regression in localization. Special shoutouts to Ann Neville, who helped me out with the Japanese LQA here!

Final Delivery

After our long process, we finally had our localized Scrabble game! See the short demo video below for how it looks in all four languages:

Lessons Learned

One of the biggest lessons learned from this was the importance of providing proper context to translators during translation, especially for software projects where short strings can bring about lots of ambiguity – and thus a higher chance of poor quality translations. We were lucky that we could go in and play the game while translating so we easily could look up where a string appeared, but in a real situation the translator likely wouldn’t have access to the game.

We learned after we finished that Phrase actually has a solution called Phrase Strings that can address part of this issue, as it is more specialized for software translation than the Phrase TMS (formerly Memsource) we used. I tried it out and saw that as a project manager, I could upload screenshots for context and utilize a “Detect Text” feature that would auto-find text on the screenshot and attempt to link them to strings in the resource file:

On the translator side in the workbench, the screenshot shows up when that string is selected so translators can see exactly where it appears in context. This is immensely helpful and if we had to do another project like this, we would make sure to take advantage of this tool.

Although it sounds cliche, the overall concept of the power of working in teams was also reinforced for us throughout the project. There was a lot of self-learning that happened as we figured out how to do everything, but it was because of the constant communication and knowledge sharing we did in our group chat that we were able to accomplish what was initially a very daunting task. We would’ve never gotten past the language switcher step had it not been for Min coming up with the idea for making something work in WPF and Silver being able to implement it in the code, and we wouldn’t have been able to tackle certain LQA issues or get a natural French translation if it weren’t for Oussama.

Being able to get exposure to working in GitHub on a team was actually pretty fun at times, and it’s opened my eyes to the possibility of wanting to learn more so that I may someday get into a technical localization position in the future!