XNA Creators Club Online
Page 1 of 1 (21 items)
Sort Posts: Previous Next

Localization in practice

Last post 4/2/2009 3:00 PM by MrLeebo. 20 replies.
  • 9/30/2008 11:16 AM

    Localization in practice

    Hello guys,

    I'm a bit concerned about localization. I just read this thread http://forums.xna.com/forums/t/10698.aspx?PageIndex=2, but the discussion is most about why to localize rather than how to localize.

    My question is about how to localize a XNA game in Visual Studio in the most effective manner. We'll be using the Latin alphabet only, with small local variations. I know that you have to consider texts and static menu or GUI images differently.

    Anyways, anybody knows of a good localization system in Visual Studio for XNA programming having both graphical assets and text in mind?

    Thanks!
  • 9/30/2008 11:51 AM In reply to

    Re: Localization in practice

    Localization Rule #1: do not embedd text in your textures.

    You save a lot of trouble to just print the text over the graphics dynamically, rather than using different sets of textures for different languages. Also, those who translate the text won't put the translation int the graphics, that will be your job and may cost you a significant amount of time.

    On the technical side, use this approach:

    Store each text in an array that keeps all language's strings, the index is the language, and obtain text like so:

    enum Languages
    {
    English,
    French,
    German,
    }
    String GetText(Int32 stringIndex)
    {
     return localizedTexts[currentLanguage][stringIndex];
    }
    String GetText(Languages lang, Int32 stringIndex)
    {
     return localizedTexts[lang][stringIndex];
    }
    

    localizedTexts can be a multidimensional array or list, or use a dictionary if you prefer that. It doesn't really matter. Just never bypass this system and never use hardcoded strings for anything if you want everything to be easily localizable.
  • 9/30/2008 1:54 PM In reply to

    Re: Localization in practice

    Thanks alot! =) I'll have a look into it.

    Any other suggestions are welcome as well.

  • 9/30/2008 2:08 PM In reply to

    Re: Localization in practice

    While such a "self-made" approach with enums/arrays will of course work, I would suggest using the built-in features of Visual Studio for localized resources. I don't have the details at hand but essentially, what you do is to have all text strings as resource strings in the string table (as key/value pairs). For this, right-click on your project, go to "Properties" and then to "Resources", I think. Select the string table (usually empty at the beginning). This default string table will be the default language. You can then add more resources (with their own string tables) for other languages, with matching key/value pairs, where you use the same keys as in the original string table, and the values are the translated texts in the corresponding language. The advantage here is, that the framework will automatically select the correct language for you, depending on the user's settings (works both on XBox and Windows), or default accordingly, if you don't have a matching language in your game.
    In your code, you then simply write "Resources.key_name_here" wherever you want the text of the given key to appear.

    Sorry that this is so "fuzzy", but I'm writing from memory here. If no one else has chimed in with more details until then, I can look it up in my project and post in more details in a while...

    Doc

    Thanks to everyone who reviewed my games! :-)

    Twitter - My Game Trailers - www.spyn-doctor.de - Games: Your Doodles Are Bugged! - Kuchibi - Golden Tangram

    Useful for peer reviews and testing your own game: My little "evil" checklist for peer review stress testing
  • 9/30/2008 2:46 PM In reply to

    Re: Localization in practice

    Are you talking about something like this http://www.ziggyware.com/readarticle.php?article_id=193?

    This system looks great, unfortually we've not worked like this from the start making it a bit tricky to change as we're quite far into the project.

  • 9/30/2008 3:39 PM In reply to

    Re: Localization in practice

    We actually have a localization sample in the works - should show up sometime over the next couple of months.

    To prepare yourself for doing this, the main thing is to load all your text from a .resx file, rather than embedding it in your source code. Even if you just have one English .resx for now (as in eg. our Network State Management sample) that will set you up ready to later add other translations.


    XNA Framework Developer - blog - homepage
  • 9/30/2008 4:13 PM In reply to

    Re: Localization in practice

    Johnny Herring:
    Are you talking about something like this http://www.ziggyware.com/readarticle.php?article_id=193?

    This system looks great, unfortually we've not worked like this from the start making it a bit tricky to change as we're quite far into the project.

    No, that's not what I meant. This is a custom solution too, as far as I can see, not the built-in solution. However, all solutions, even the built-in solution, will not come cheap if you are already far into your project and currently have all strings hard coded. Because all solutions are similar in one way: You have to pull out all hard coded strings from your code and put them into key/value-structured lookup tables/arrays/whatever, and instead of having the hard coded text in the code, you then have a lookup access in your code, with the matching key for that occasion. This is a bullet you will have to bite if you want localization (which is why it's always a good idea to support localization right from the start. :) )

    The built-in system has the advantage, that it handles the language detection automagically:

    In the solution explorer, right-click on the project name, then select "Properties". Then from the tabs on the left, select "Resources". If it says "This project does not contain a default resources file. Click here to create one.", then do so, i.e. "click here".
    What you get is the default string table, where you can enter resources with "name" and "value" (and a "comment", but I seldomly use this). This is the key/value pair I was talking about (only they call it name, instead of key).
    This default string table is for the default language: The framework will always try to read the settings of the user (i.e. either the Windows settings or the XBox settings) to find out which locale the user has currently selected. The framework will then try to use the string table that matches the language for this locale. If there is no matching string table, the framework will then select the default string table. So it is usually best to use English in this default string table (unless you are targeting a local market, but then you probably wouldn't be asking about localization in the first place).

    So what you do is, that for any text that is used anywhere in the game, you make an entry here in this string table, with the English text as the "value" and a meaningful name as the "name". Then in your game, at any location where you need this text, instead of writing the text string itself, you write "Properties.name" instead, where you replace "name" with the name of the text that you want to appear. Which is why you should use a "meaningful" name, so that in your code, the "name" will give you a clue of what text will later be used.

    For example, if you have a "settings" dialog that is supposed to have the title "Game Settings", then in the string table you would create an entry

    Name:                  Value:
    SettingsDialog_Title   Game Settings

    and in your code, wherever you need this text you would simply write "Resources.SettingsDialog_title". For example:

    dialog.SetTitle(Resources.SettingsDialog_Title);

    (You may need a "using YOURGAME.Properties" directive for the "Resources" class to become available.)

    Transfer all your hard-coded texts into the string table in this fashion. At the end, you will have a game that will always display in the default language (assumably English).

    Actually, to edit the string table, you don't have to go via Solution Explorer -> Right Click Project -> Properties -> Resources. There's also a direct access to this table:

    In your solution explorer, under the project, there's a folder called "Properties". If you open it you will now find a file called "Resources.resx". Just double click this file to open the default string table.

    Then you can start to localize the game for a new language, by adding another string table, which comes in form of another Resources.resx file, only with a slightly different name for each language: The name is Resources.xx.resx, where you need to replace xx with the two-letter language code (lower case) of the desired language. For example, if you wanted to do German, you would need a file called "Resources.de.resx".

    In Visual Studio 2005 Express there only seem to be "roundabout" ways for creating such a Resources.xx.resx file (this may be improved in VSE 2008?). The easiest one is probably this one:

    In the solution explorer, right click on the project name, then select "Add -> New Item". In the dialog, make sure to select the "Resources File" template and as the name, enter "Resource.xx.resx" (with "xx" replaced according for your target language).

    This will create the file in the project root folder. From there you need to move it to the "Properties" folder. Cut&Paste won't work, because the right-click menu on the "Properties" folder doesn't offer "Paste". But you can simply move the file with drag&drop. I.e. inside of the solution explorer, simply drag the file from its location in the project root folder into the "Properties" folder.

    Double clicking the file now opens a string table similar to the default string table describe above - only initially empty.

    Copy all entries from the default string table to this language specific string table, then translate the texts in the "Value" column to your target language. If you later add more entries to your default table, remember to also add them to all language specific tables (and translate them there). Or if you change a value in the default table, also change it in the language tables. Similarly for deleting values...

    That's it, nothing more to do! Especially: You don't need any code changes to support the new language!

    If you faithfully used "Resources.name" everywhere in the code (as described above), then each occurrence of a certain "name" will automatically be replaced with the value from the language specific string table that matches the language settings of the user (in Windows or the XBox dashboard), or if there is no specific language table for that language, the text from the default table will be used.

    Doc

    P.S. You may notice that in the solution explorer the Resources.resx file has a little "+" icon before it, that you can use to unfold a "child" file called Resources.Designer.cs. But the Resources.xx.resx files don't have this. You can safely ignore this. It's part of the framework "magic" that you don't need to care about (and you also don't need to edit the Resources.Designer.cs file, as this file is generated automatically).

    P.P.S. The Resources.xx.resx files are XML, so if you have a translater who doesn't work with Visual Studio (for example an external translator) then he can edit the XML directly.

    Thanks to everyone who reviewed my games! :-)

    Twitter - My Game Trailers - www.spyn-doctor.de - Games: Your Doodles Are Bugged! - Kuchibi - Golden Tangram

    Useful for peer reviews and testing your own game: My little "evil" checklist for peer review stress testing
  • 10/1/2008 9:29 AM In reply to

    Re: Localization in practice

    Thanks alot guys, you're awesome!

    Shawn: I look forward to see the solution you're up to.

  • 10/1/2008 10:03 AM In reply to

    Re: Localization in practice

    Johnny Herring:
    Shawn: I look forward to see the solution you're up to.

    The .resx file solution Shawn mentioned (for which the XNA team has a sample in the works) is exactly what I have described above. (At least that's what I assume. :) )

    Doc

    Thanks to everyone who reviewed my games! :-)

    Twitter - My Game Trailers - www.spyn-doctor.de - Games: Your Doodles Are Bugged! - Kuchibi - Golden Tangram

    Useful for peer reviews and testing your own game: My little "evil" checklist for peer review stress testing
  • 10/1/2008 2:28 PM In reply to

    Re: Localization in practice

    Ahh thanks Spyn Doc, that's even better news. =)
  • 10/1/2008 4:07 PM In reply to

    Re: Localization in practice

    Our sample shows how to use .resx files for string localization, plus some other stuff: how to localize other non-text assets (textures, sounds, etc), and how to build fonts for East Asian languages with ridiculously large character sets.
    XNA Framework Developer - blog - homepage
  • 10/2/2008 9:31 AM In reply to

    Re: Localization in practice

    I can't seem to find the Properties namespace anywhere, I tried the RootNamespace defined in the project xml, I tried browings through the system namespace. Some page on msdn said it is located in the namespace with the same name as the visual studio project but I can't even find that...I'm kind of lost here.
  • 10/3/2008 5:32 PM In reply to

    Re: Localization in practice

    If your project is a standard game project (created from a VS template), then in your project folder you should have a folder "Properties", which by default contains the "AssemblyInfo.cs" class. If you add the default resources (as described in my posting above, via the "Click here to create one" link), then this is where the Resources.resx file will be created too. So that's the folder/namespace you are looking for). All you need should be a

    using PROJECT_NAME.Properties;

    line in your code...

    Doc

    Thanks to everyone who reviewed my games! :-)

    Twitter - My Game Trailers - www.spyn-doctor.de - Games: Your Doodles Are Bugged! - Kuchibi - Golden Tangram

    Useful for peer reviews and testing your own game: My little "evil" checklist for peer review stress testing
  • 10/3/2008 5:40 PM In reply to

    Re: Localization in practice

    Very strange, my project name is ColosseumWin and it cannot be found as a namespace at all. I have a Resources.rsx in my Properties folder and I created it just the way you described. I'm starting to think that this may have something to do with us having manually modified the project xml...although not in a particulary advanced way. Any further thoughts? Thanks for the help.

    Regards

  • 10/4/2008 9:16 AM In reply to

    Re: Localization in practice

    I put the texts in a XML, then you only need 1 XML and 1 SpriteFont for any language implementing the 'How To: Extend the Font Description Processor to Support Additional Characters' example as you need special characters for some languages, and with 1 SpriteFont for any language you remove that worry, selecting the corresponfing text file for any language in content properties. Then, you only need to implement:
    • Create a 'String language' var. to store the language.
    • At beginning you can auto-select from system config., and allow users to modify it manually. How to do this:
      • User selection is easy, you have options and then assign the correct 'language=es', 'language=en', language=jp', etc. depending on user selection.
      • Auto-selection, simply implement a method like this:

            public void SetGameSystemLanguage() 
            { 
                int culture = CultureInfo.CurrentUICulture.LCID; 
                switch ((culture & 0x00FF)) 
                { 
                    case 0x000a: //español 
                        szLanguage = "es"
                        break
                    case 0x0011: //japonés 
                        szLanguage = "jp"
                        break
                    default//inglés 
                        szLanguage = "en"
                        break
                } 
            } 

     See that the szLanguage is the 'String language'. You have all the codes in documentation, we generally only need the last 8-bit.

    Then now you only in the LoadContent() methods add the language string to localized contents, so for texts we have: texts_en.xml, texts_es.xml, text_jp.xml, and maybe for some textures we have poster_en, poster_es, poster_jp, etc. See that the important is the content name, so text_en.xml is text_en to do the following:

    Content.Load<Type>("content_" + language); look at the '_' added, this depends on your content names, I usually add the '_' for no confusing names (like textsen).

    And voilà, you have your localized content of any type loaded. If you want to change language with no need to quit and restart the game you only need to reload the current loaded content.
  • 10/4/2008 9:28 AM In reply to

    Re: Localization in practice

    HerrUppoHoppa:
    Very strange, my project name is ColosseumWin and it cannot be found as a namespace at all. I have a Resources.rsx in my Properties folder and I created it just the way you described. I'm starting to think that this may have something to do with us having manually modified the project xml...although not in a particulary advanced way. Any further thoughts? Thanks for the help.

    You mean you do have the Properties folder and you do have the Resources.resx file in it, but if you include "using PROJ_NAME.Properties;" in a class file you still can't access the "Resources" class? That's very strange. Don't know how that could happen. An idea to test this: Create a new dummy (game-)project and see if it works in the dummy project. If yes, then it must certainly be something wrong in the configuration of your main project. Maybe by comparing the configs of the dummy and the main project you can spot the difference that causes this?

    Doc

    Thanks to everyone who reviewed my games! :-)

    Twitter - My Game Trailers - www.spyn-doctor.de - Games: Your Doodles Are Bugged! - Kuchibi - Golden Tangram

    Useful for peer reviews and testing your own game: My little "evil" checklist for peer review stress testing
  • 10/4/2008 1:22 PM In reply to

    Re: Localization in practice

    Thank You Spyn Doctor for the detailed instructions on how to use the resource string tables for localization. I was able to create my Resource.resx and access the strings that were in the table just fine. My language is set to English, so for testing purposes I set my Resource.resx to be Spanish and I the created a Resource.en.resx with English tables. When I try my project I am only getting the default table (the Spanish text) and not the English. How have you been able to test your localization to make sure the correct .resx file was being used?

    Thanks,

    Nifty

  • 10/4/2008 7:56 PM In reply to

    Re: Localization in practice

    Hi Nifty,

    actually, I'm not sure which setting to change in Windows to test this, as I only tested this on the XBox (there I simply changed the language setting in the dashboard). But it should be somewhere in the Windows settings. If unsure, maybe look it up on MSDN?

    BTW, I would recommend the reverse: Make English the default and put Spanish (and whatever other languages you also support) into the additional Resources.xx.resx files.

    Because every user who has set a language that you do not support will automatically get the default language. So let's assume that you support the "big" languages like Spanish, French, English, German, Italian, Portugese , maybe Japanese/Chinese. Maybe more? No matter how many languages you support, the list will probably never be complete. There will always be people with an unsupported language. Maybe Swedish? Or Greek? Croatian? Whatever. All these people would then get the default language. So in your case Spanish. But, and no offense against Spanish as a language intended here, I would think that English would be the better default for the vast majority of such people who have an unsupported language setting.

    Doc

    Thanks to everyone who reviewed my games! :-)

    Twitter - My Game Trailers - www.spyn-doctor.de - Games: Your Doodles Are Bugged! - Kuchibi - Golden Tangram

    Useful for peer reviews and testing your own game: My little "evil" checklist for peer review stress testing
  • 10/6/2008 1:20 PM In reply to

    Re: Localization in practice

    Spyn Doctor:

    HerrUppoHoppa:
    Very strange, my project name is ColosseumWin and it cannot be found as a namespace at all. I have a Resources.rsx in my Properties folder and I created it just the way you described. I'm starting to think that this may have something to do with us having manually modified the project xml...although not in a particulary advanced way. Any further thoughts? Thanks for the help.

    You mean you do have the Properties folder and you do have the Resources.resx file in it, but if you include "using PROJ_NAME.Properties;" in a class file you still can't access the "Resources" class? That's very strange. Don't know how that could happen. An idea to test this: Create a new dummy (game-)project and see if it works in the dummy project. If yes, then it must certainly be something wrong in the configuration of your main project. Maybe by comparing the configs of the dummy and the main project you can spot the difference that causes this?

    Doc

    Yes that is exactly what I mean, and infact I get a compilation error on the project name as a name space. I tried creating a new dummy project and it worked instantly so I guess it's due to manual modifications. Thanks for the help.
  • 3/28/2009 7:40 AM In reply to

    Re: Localization in practice

    Shawn Hargreaves:
    We actually have a localization sample in the works - should show up sometime over the next couple of months.

    To prepare yourself for doing this, the main thing is to load all your text from a .resx file, rather than embedding it in your source code. Even if you just have one English .resx for now (as in eg. our Network State Management sample) that will set you up ready to later add other translations.

    Shawn,

    Thanks for the information.  I was looking at some existing articles on localization at Ziggyware (Language Localization and Language Localization using Extension Methods).  Both use XML files for targeted languages, although the "Extension Methods" articles uses the .NET ResourceManager and ResXFileCodeGenerator to compile the ResX resources into DLLs.  I wasn't sure if this method would work on the Xbox360, but I later discovered that the sample you mentioned was already released, and it uses a similar method of localizing text.

    I will use the Creators Club example as reference (Localization).

    Thanks again!

    Michael


  • 4/2/2009 3:00 PM In reply to

    Re: Localization in practice

    As the author of the Extension Methods article, that solution doesn't use XML files... Well, no more than C# projects in general use it.
Page 1 of 1 (21 items) Previous Next