magarena / magarena

Magarena is a single-player fantasy card game played against a computer opponent.
http://magarena.github.io
GNU General Public License v3.0
410 stars 96 forks source link

Translatable UI #387

Closed lodici closed 9 years ago

lodici commented 9 years ago

56d8f7b1ebd9ee0e7fcca1ff1c1de933ceb13f1d is a first stab at a translation mechanism for Magarena aimed at the display of UI text and messages (card data is a whole other kettle of fish). It should work with both static strings and strings containing place holders (ie. String.format(...)). It is designed to be simple to use for translators with minimal overhead for developers in terms of workload.

For this initial commit I have implemented translatable strings for the Main Menu (6f852adecabdc53ec3007bcdb8c4e9f6385f3b43), Settings Menu (efda37c8d7e2c5dbb4f9c2a8cba064ef73976681) and the Preferences dialog (e33fd2c4338c0fd810ea30569a819c33940f5caa) which has alot of text. I hope we can have close to 100% coverage by release of 1.64.

I am currently working on a wiki page which will explain how it all works and I will post the link here when I have published the first draft. But to summarize...

This adds a new option to the preferences dialog which basically uses reflection and a simple convention to automatically extract (English) strings to a text file in Magarena/translations which can then be replaced with appropriate translations.

From a developer POV, to make a string translatable it should be defined as a constant (public static final) with a name starting with _S. The three commits above demonstrate how I did this. Finally, replace the inline string with UiString.get(???) or UiString.get(???, <args>..), where ??? is the equivalent _S* reference. That's it really.

This also introduces code to restart Magarena. Might be hit and miss how well this works, but seems to work ok on Windows and Linux (with one exception).

lodici commented 9 years ago

With the help of Google Translation, I have no idea how accurate these are but I hope they convey the gist fairly well.

Chinese Simplified translation file screenshot00179 español screenshot00181

PalladiaMors commented 9 years ago

I've always wanted to help you with something to compensate for all the work I've thrown at you with requests, so I guess this could be a good way to do that. Maybe I could also make a decent guinea pig to check if anybody can use the new feature. I'll take responsibility for the Portuguese translation if you can explain how to start it. I lived in France for a while and do speak some French, but I really don't trust my grammar very much and it would definitely be better to find a native speaker.

lodici commented 9 years ago

Great - the UI is pretty rudimentary at the moment so I would appreciate any suggestions on how it can be designed to make a translator's life easier. That is my primary concern here - usability from a translator's POV. Saying that I still think it should be fairly intuitive (if a bit clunky).

  1. First you will need to download the latest build (#1458 or later).
  2. Open the preferences dialog and the first setting you will see under the General tab is the User Interface language.
  3. Click New and enter the name of the translation file (eg. português).
    This will create a new text file named português.txt in the Magarena/translations directory and should open it in the default text editor. If it fails to do this, right click on the language combo/dropdown to open the folder instead.
  4. Click Edit to open the file for an existing translation in the same way. This will also automatically add any new strings to the top of the file so it is easy to see what is new.
  5. Close the preferences dialog and make sure you Save to set the UI to the new translation file - you will be prompted to restart Magarena.

The translation file itself contains all the strings (in English) I have pulled out of the UI so far. Expect this to increase throughout the rest of the month.

Each translatable string is stored on a separate line and is associated with an ID number which should be ignored and not altered. Instead, simply replace the English text after the equals sign with the appropriate translation. Some of the text will contain place-holders (e.g. %s, %d, \n) which are replaced at runtime with dynamically generated data. These should be left as-is although the position within the text string may need to be changed as appropriate for the given language. The small unicode square prefix is simply a visual indicator that helps to identify untranslated text both in the file and also when displayed in the UI. Remember to save regularly!

Assuming you have set the translation in settings then the next time you start Magarena it will load the translation file and use its strings in place of the English default in the UI.

PalladiaMors commented 9 years ago

During step 3, I get the following error message:

"Could not open translation file. java.io.IOException: Unable to locate JAR file!

To manually specify the location please use the '-DjarFile' VM option."

Right clicking the dropdown opens the translations file, which is currently empty.

I suppose I have to execute Magarena with that -DjarFile option, will try to execute - DjarFile next.

lodici commented 9 years ago

Are you running from an IDE (Nebeans, Eclipse)? I should have mentioned that in that case you should add the -DjarFile argument. For example, I use Netbeans and I have -DjarFile=dist\magarena-github.jar.

EDIT: No I am getting it too when running Magarena.exe directly. Damn.

PalladiaMors commented 9 years ago

I've no idea what IDE, Netbeans or Eclipse are.

My OS is Windows 8. I've downloaded java 8 update 45 in order to run java applications. All I do when I run Magarena is click on the executable.

Will create a shortcut with the command above and report if somehow I run into trouble 0_0

Edit: My Magarena path is C:\Magarena

I'm running from a shortcut with the path C:\Magarena\Magarena.exe -DjarFile=dist\magarena-github.jar

Still getting the error message in the post above.

lodici commented 9 years ago

I think you will struggle with that too - for me it creates the file but it is empty. Will need to take a look at Magarena.exe.

lodici commented 9 years ago

Just added a fix (I think), now just have to wait an hour and a half for build server to finish. :-1:

You definitely should not have to add DjarFile - that is a dev option.

PalladiaMors commented 9 years ago

Roger, as soon as it finishes I'll pick it up and tell you what's going on here.

lodici commented 9 years ago

Still fails, it is going to require a build config update to fix I think (see #389).

PalladiaMors commented 9 years ago

Confirm still not working over here, although I'm not sure if I caught your fix due to the gray build thing.

lodici commented 9 years ago

@PalladiaMors it should all be fixed now in latest build (#1460+). Tested successfully on Windows 7 and Linux Mint 17.

PalladiaMors commented 9 years ago

@Lodici: currently working on it. One thing I'm definitely missing is the fact that we have no information whatsoever about where each individual piece of text is found. For instance, the word "theme" can have two different meanings in English: in can mean "subject", or it can mean "song". If I knew which menu this word is coming from, it would be simple to figure out what's the proper meaning in this particular case, but without that info, there's obviously the risk of a mistaken translation.

Edit: OK, I'm translating with Magarena open and I think I can locate where most of the text comes from. That's indeed important: for example, this is a third meaning of the word theme, related to 'appearance'.

lodici commented 9 years ago

One thing I'm definitely missing is the fact that we have no information whatsoever about where each individual piece of text is found

This is always going to be a problem. The more familiar you are with Magarena (and English) then the easier it should be to guess the context. But I cannot think of a consistent way of adding the required context info to the translation file.

I would go with your best guess and even if turns out to be wrong I would not worry since if there are enough people using the translation it should soon be called out. Always feel free to ask for clarification. I am happy to help.

Theme - setting used in the Look & Feel tab of the preferences dialog.

lodici commented 9 years ago

Which does raise the subject on how to publish a translation file.

Best case would be to include it in a release which also means adding it to the source code repository. But to be useful it would also mean keeping the translation file up-to-date during the monthly development cycle or at least prior to a release. I am not sure whether that would be considered a problem or not. I guess it would depend on the diligence of the translation file maintainer(s) and the amount of new text being generated by the pesky developers.

But I also like the idea of using the forum as the gathering point for all things translatable since I think this will attract more people to play Magarena as well encourage additional translations. To that end I am thinking that we could add a new Translations sub-forum which contains a topic thread for each translation. The first post in the thread would contain the translation file as an attachment and instructions (in the appropriate language obviously) on how to install. The rest of the thread could be used as a sort of unofficial support forum for the native language speakers.

PalladiaMors commented 9 years ago

What's "spinner values"?

lodici commented 9 years ago

These are the spinners in question. screenshot00185 If you feel anything is unclear, a bit technical or jargon heavy please feel to paraphrase if it will make it clearer.

lodici commented 9 years ago

Also, don't go out of your way to make a translation fit in the space allotted to it by the UI. If it does not fit then we should look at updating the UI to accomodate the variable sizes required.

PalladiaMors commented 9 years ago

Just to note it somewhere, I'm going to mention here some word choices that I ended up having to make:

Popup: there's no direct translation of this word. Depending on the context, the English word popup itself is used (for example, annoying internet ads are popups). In Magarena, it's usually used for the image that "pops up" when you hover the mouse over a card. Thus I'm translating each instance as "card image popup" instead of using just the word "popup" in order to ensure this is understandable.

AI: while in English this is immediately recognizable as the short for "Artificial Intelligence", this isn't true for the Portuguese equivalent "IA". I'm opting to translate it as "opponent" (actually "adversary", which is the typical word in Portuguese). I just can't see a way around this, using the term "artificial intelligence" all the time to mean the computer opponent is going to be difficult to understand for a lot of people.

Edit: the alternative I can see is using the term "computer". When you play chess against a computer, the opponent is usually referred to as "computer" (in English I believe this is also true, although the term "engine" can also be used, which isn't true for Portuguese). Another possibility perhaps is actually identifying the virtual opponent with Magarena and calling it "Magarena" (as Chessmaster's engine can definitely be referred to as "Chessmaster" as well). In principle my stance is to insist in using "adversary".

PalladiaMors commented 9 years ago

Getting this error when I try to load the translation in order to test it:

CRASH REPORT FOR MAGARENA THREAD Thread[AWT-EventQueue-0,6,main]
CREATED ON 2015/07/02 22:36:18
MAGARENA VERSION 1.64, JRE 1.8.0_45, OS Windows 8.1_6.3 x86
================================
Used Memory: 90M
Free Memory: 156M
Total Memory: 247M
Max Memory: 494M
================================
-Xms256m
-Xmx512m
-Xverify:none

Exception from controller.runGame: For input string: "?0890925982"
java.lang.NumberFormatException: For input string: "?0890925982"
    at java.lang.NumberFormatException.forInputString(Unknown Source)
    at java.lang.Long.parseLong(Unknown Source)
    at java.lang.Long.valueOf(Unknown Source)
    at magic.ui.UiString.getStringsMapFromFile(UiString.java:85)
    at magic.ui.UiString.getUnescapedStringsMap(UiString.java:95)
    at magic.ui.UiString.loadTranslationFile(UiString.java:108)
    at magic.ui.prefs.PreferencesDialog.doOkButtonAction(PreferencesDialog.java:470)
    at magic.ui.prefs.PreferencesDialog.actionPerformed(PreferencesDialog.java:488)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.WaitDispatchSupport$2.run(Unknown Source)
    at java.awt.WaitDispatchSupport$4.run(Unknown Source)
    at java.awt.WaitDispatchSupport$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.awt.WaitDispatchSupport.enter(Unknown Source)
    at java.awt.Dialog.show(Unknown Source)
    at java.awt.Component.show(Unknown Source)
    at java.awt.Component.setVisible(Unknown Source)
    at java.awt.Window.setVisible(Unknown Source)
    at java.awt.Dialog.setVisible(Unknown Source)
    at magic.ui.prefs.PreferencesDialog.<init>(PreferencesDialog.java:223)
    at magic.ui.ScreenController.showPreferencesDialog(ScreenController.java:191)
    at magic.ui.screen.SettingsMenuScreen$1.actionPerformed(SettingsMenuScreen.java:45)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
lodici commented 9 years ago

Please can you post the contents to a gist or email me the file (lodici123@gmail.com). Thanks.

lodici commented 9 years ago

Getting this error when I try to load the translation in order to test it:

Not being able to examine the actual file makes it a bit of a guess, but I am pretty sure it is related to the encoding of the file. I have found that unless it is UTF-8 without BOM this particular error keeps cropping up and I can generate a similar error fairly easily. I think we are going to need to do this within Magarena to avoid these kind of pitfalls using an external text editor.

PalladiaMors commented 9 years ago

Just sent you the file through e-mail. Maybe I'm wrong but if I understand correctly these errors are related to symbols that are specific to certain languages. I believe Portuguese contains exactly two such characters, "ç" and "ã".

By the way, I've already noticed a couple things in the file I sent you that I'd like to change, so that's definitely not the final version.

Edit: thinking about it, I realize I made the extremely stupid error of using NotePad again, which we already KNOW causes these problems. What an idiot I am. I'll fix it using another text editor.

Maybe some kind of warning that NotePad shouldn't be used to do these translations could be useful. I had already come across this issue and should know better, but it could confuse people who aren't aware.

lodici commented 9 years ago

Just sent you your file re-encoded. Looks good by the way although there is no need for the prefix square (unless you left that in intentionally).

Edit: thinking about it, I realize I made the extremely stupid error of using NotePad again, which we already KNOW causes these problems. What an idiot I am. I'll fix it using another text editor.

The thing is you should not really have to worry about stuff like encoding or what text editor you are using. This has kind of convinced me that we will need to implement a translation screen in Magarena before the next release.

PalladiaMors commented 9 years ago

I've saved it using WordPad and now it's no longer crashing. However, while it doesn't crash, it's not loading either, which would be useful to check it a bit better. I've tried restarting, but still doesn't work. What should I do?

Will remove the squares, for some reason I thought that shouldn't be changed.

lodici commented 9 years ago

If you save the file I sent you directly to the Magarena\translations folder from the email that should load without any issues. If you edit it and save using Notepad or WordPad then it will most likely use a different encoding and you will end up with the same problem. Take a look at NotePad++ as an alternative text editor, it is very good (and free).

PalladiaMors commented 9 years ago

@Lodici, currently reviewing the work. Could you please explain a bit what happens when the highlight overlay option is chosen? I'm a bit unsure on how to translate this, I've chosen the word "cover" for "overlay" for the time being, would that make sense?

After thinking things through, I've decided to go with the word "computer" for the AI. Looks like the simplest and most easily understandable option.

I've also noticed that the deck editor isn't actually getting translated, although I'm sure I've changed that part of the text as well.

Should I send you this update by mail when it's finished? Or should I post it on the forum instead?

lodici commented 9 years ago

@Lodici, currently reviewing the work. Could you please explain a bit what happens when the highlight overlay option is chosen? I'm a bit unsure on how to translate this,...

Good question. The whole card is highlighted using a transparent color overlay to indicate it is a valid selection. Personally I would prefer just the border higlight but it is a legacy thing I guess.

... I've chosen the word "cover" for "overlay" for the time being, would that make sense?

Not in English, but if you think "cover" conveys the same meaning in Portuguese then go for it.

After thinking things through, I've decided to go with the word "computer" for the AI. Looks like the simplest and most easily understandable option.

I think computer is good choice. You could argue we should use that in English as well.

I've also noticed that the deck editor isn't actually getting translated, although I'm sure I've changed that part of the text as well.

Not yet. I am gradually working my way through the UI classes. But it is pretty boring! :wink:

Should I send you this update by mail when it's finished? Or should I post it on the forum instead?

I would go with the forum, that is how I think translations should be submitted in future and will be interesting to see what interest your post elicits.

Thanks for all your help btw, it really is useful to have someone test-driving the code.

lodici commented 9 years ago

I have done all deck editor classes although the column headings in the cards table still need to be looked at. I have also added an ability to comment on a string so that it might help the translation, for example...

# 107393066 eg. Memnite is illegal in Standard.
0107393066 = <html>%s <b>%s</b> in %s.</html>

Let me know if this is useful or not.

lodici commented 9 years ago

I have reviewed and updated all the UI package classes, ending up with a total of just under 500 strings eligible for translation. I ignored TextMode and still have to look at the import dialog and the column headings in the cards explorer/deck deck editor screens so I guess probably 20 to 30 more strings to go.

PalladiaMors commented 9 years ago

This may be a bit of a stupid question, but... how do I add al the new translatable text to the translation file without erasing all the work I've previously done?

The word overlay is quite a challenge indeed. I agree with you that "cover" isn't quite adequate. In the end, I suppose what the highlight overlay option really does is highlight the card - the inside of the card - so maybe I could just use the word "card". An alternative would be using the word "filling", but that could be a bit weird as well. Perhaps I'll just leave it in English, I've done that with so many words already. Translating computer-specific terms isn't so easy, I had done translations before but never anything related to informatics, which is a bit of a challenge. Magic itself has its share of specific terms as well. Forget about doing the French translation, I'm completely sure at this point that I'm not capable.

Also, looks like I stole this issue to discuss stuff that was totally unrelated to it. Maybe it would be a good idea to open a new one later?

lodici commented 9 years ago

This may be a bit of a stupid question, but... how do I add al the new translatable text to the translation file without erasing all the work I've previously done?

Select the translation in preferences and click on Edit in the drop down. This actually synchronizes the translation file with the current UI. New entries will be added to top of the file above existing translations.

lodici commented 9 years ago

Unfortunately the latest build failed again (during AI testing). @melvinzhang please can you restart if possible. It really is annoying. And confusing because even though it has failed it still has downloadable zip files but which appear to be from the last successful build. You would think on fail it would hide these files.

lodici commented 9 years ago

so maybe I could just use the word "card".

That makes sense. Note, if you want to clarify you can always add more details to the tooltip (1643521398). Also it does not have to be a single word either, the combo should resize to fit.

lodici commented 9 years ago

Also, looks like I stole this issue to discuss stuff that was totally unrelated to it. Maybe it would be a good idea to open a new one later?

I will keep this issue open for the rest of the month to discuss any translation-related issues so I have no problems with you posting here. Maybe use your forum post to discuss issues related directly to the portuguese translation?

lodici commented 9 years ago

I have added a wiki page. Feel free to update if I have missed anything.

lodici commented 9 years ago

I have added a new screen which is displayed the first time Magarena is run post install and which lets the user select their preferred language for the UI before even the main menu is displayed. screenshot00190 For this to work then we need to distribute translations with a release which means adding the translation file to GitHub (which I have already done). This is obviously much more convenient to the user. I think we could use the forum as the initial place to contribute a new translation and then once it reaches a minimum % coverage of the UI it becomes a candidate as an "official" translation that gets added to GitHub and is included in each release. You can actually edit the file directly from GitHub which would be useful for small updates and of course you have full change history. @PalladiaMors what do you think about maintaining a translation via GitHub?

melvinzhang commented 9 years ago

Sounds good, we should distribute the translations with the release. What happens if the translation falls below the minimum % coverage in the future?

On Fri, Jul 10, 2015 at 3:42 PM, lodici notifications@github.com wrote:

I have added a new screen which is displayed the first time Magarena is run post install and which lets the user select their preferred language for the UI before even the main menu is displayed. [image: screenshot00190] https://cloud.githubusercontent.com/assets/2443519/8614050/d1e617f4-26dd-11e5-8e01-c1b717eedc89.png For this to work then we need to distribute translations with a release which means adding the translation file to GitHub. This is obviously much more convenient to the user. I think we could use the forum as the initial place to contribute a new translation and then once it reaches a minimum % coverage of the UI it becomes a candidate as an "official" translation that gets added to GitHub and is included in each release. You can actually edit the file directly from GitHub which would be useful for small updates and of course you have full change history. @PalladiaMors https://github.com/PalladiaMors what do you think about maintaining a translation via GitHub?

— Reply to this email directly or view it on GitHub https://github.com/magarena/magarena/issues/387#issuecomment-120270296.

lodici commented 9 years ago

Sounds good, we should distribute the translations with the release. What happens if the translation falls below the minimum % coverage in the future?

Ok, a bit more detail (just some ideas)...

melvinzhang commented 9 years ago

:+1: Can these rules be encoded in the program so that it detects out of date translations automatically?

lodici commented 9 years ago

At this early stage I am not sure that is necessary. I see the above points as just rules-of-thumb, something to use to decide how relevant a translation is prior to each release. The final decision would probably come down to the translator who is best placed to make that call. In time and assuming the translation mechanism ellicts many contributions we should be able to refine what works and maybe identify rules that can be automated.

lodici commented 9 years ago

Can now switch languages in preferences without needing to restart Magarena.

melvinzhang commented 9 years ago

Is the translation system designed in a way that lets us compute the translation coverage percentage? It would be something good to show on the UI as well to help the user decide whether to use a particular translation.

Are the mapping between translations via the _S* name or via the English text itself? From a quick reading of UiString it seems to be based on the CRC of the English text. In that case, if the English text is changed slightly, wouldn't that invalidate the existing translations?

lodici commented 9 years ago

Is the translation system designed in a way that lets us compute the translation coverage percentage? It would be something good to show on the UI as well to help the user decide whether to use a particular translation.

I think it would be useful to translators but as a user if it says portuguese (98%) or portuguese (48%) well I think that is too much info ("78%? Should I use or not? Aarrghh! too many decisions"). Either the translation is useable or its not. I think that decision is up to us or more likely the translator.

Still if you are interested take a look at doEditTranslationFile() in TranslationPanel.

Are the mapping between translations via the _S* name or via the English text itself?

Via the English text as a CRC number.

In that case, if the English text is changed slightly, wouldn't that invalidate the existing translations?

Absolutely. So then you would want to notify the translators - I thought of adding a post to the release thread listing the new strings.

melvinzhang commented 9 years ago

Using the text itself may be too brittle, we may make small correction or changes to the text but the meaning is unchanged so the translation would not have to change. Can we used the _S* name instead, i.e. UiString.get("_S1") instead UiString.get(_S1). For changes that will break translations, such as adding a new argument to a template, we can introduce a new _S* symbol.

lodici commented 9 years ago

Using the text itself may be too brittle, we may make small correction or changes to the text but the meaning is unchanged so the translation would not have to change.

It may or may not, until it has run for a bit I don't think we can be sure either way. Certainly the UI text does not change much. Obviously if we find that translation coverage is constantly dropping because translators are fed up with having to update then it might require a re-think. Perhaps @PalladiaMors has an view on this?

Can we used the _S* name instead, i.e. UiString.get("_S1") instead UiString.get(_S1)

That would be a pain to maintain since you would lose the auto-suggest / reference capabilities of the IDE. Currently I can move my cursor over _S1 and it will show me its value - that is why I can name the constants _S1, _S2 etc. That would not work with "S1". It is important that it is easy to use for development as well.

PalladiaMors commented 9 years ago

Well I'm always around anyway, so I'll update as necessary. Small updates surely aren't too much trouble. I think there might be still some pieces of text here and there that aren't translatable yet (spotted the text for May Choices, for example). Right now the translation file has about 500 lines of text, which means about 10 pages of total text (~60 lines per page?), which isn't too much trouble.

Right now I think the biggest challenge will be finding translators. Which leads to figuring out which languages are the priority. On principle one would think that the most spoken languages should be the priority, but I don't know if this necessarily applies to Magarena. For instance, the most spoken language in the world is Mandarin, but I don't know if MtG is too popular in China right now. I don't know if you guys have data related to download IPs or whatever that could help figure out where Magarena is most popular. From playing MtG online in international servers, my opinion is that German and Spanish would probably be the most relevant translations right now. Maybe you guys know someone who could help with those?

lodici commented 9 years ago

500 lines seems a lot to me! Although apart from the import (still TODO) I think that is just about every UI string accounted for so I guess the thing is that there is that initial effort required then it should just be a relatively small number of updates every release. If you could get multiple people working on the intial translation that would help which is where the forum comes in but as you say it depends on how many people want to actually do a translation. I hope using a language selector at startup should help to promote the idea and possibly encourage someone to have a go.

It should also be noted that this has been aimed very much at the UI "static" text, if you like. The way I see it there are two addional areas you would need to look at to make Magarena fully multilingual.

The first is the card images. I have no idea how easy it is to come by images in another language if indeed they are in fact available. But I don't see it being too difficult to implement through the use of sub-folders (eg. pt, `en,fr``, etc) if someone wanted to override the default images.

The second is text generated during game play predominantly displayed in the (UI) game log. This is very much @melvinzhang and @ShawnieBoy's domain but my initial thoughts are that it would be a significant challenge but hopefully not competely impossible.

ps. regarding language popularity. I wrote some software many years ago which was designed to be multilngual. I thought the first translations would be French or Spanish. But the first contribution I received was a Portuguese translation as well.

lodici commented 9 years ago

Import UI has been updated with about 20 new translatable strings. screenshot00192

lodici commented 9 years ago

Just about there I think (at least for this dev cycle) with a few new strings to translate...

2270227889 = ▫Hand
1849532704 = ▫Library
0454249737 = ▫Graveyard
1261234564 = ▫Exile
3689109508 = ▫Play a card or ability.
# 3864448769 eg. {f} will be replaced by an icon.
3864448769 = ▫Click {f} or Space to pass.
# 2670693515 eg. | represents a new line. Position to fit text in user prompt.
2670693515 = ▫Right click {f} or Shift+Space to|skip till end of turn.
# 1529602839 eg. this is the AI level.
1529602839 = ▫Level
0026555175 = ▫Playable cards, missing images
0557509002 = ▫Unimplemented cards, missing images