#67 closed enhancement (fixed)
[PATCH] Internationalization
Reported by: | Stuart Walpole | Owned by: | gallaecio |
---|---|---|---|
Priority: | Release Blocker | Milestone: | Alpha 16 |
Component: | Core engine | Keywords: | patch |
Cc: | swyterzone+wildfire@… | Patch: |
Description (last modified by )
- i18n - allow conversion from game's text into a translatable table, and then to the right format for the game to read. Possibly using GetText (http://www.gnu.org/software/gettext/gettext.html) if it supports XML, JS, and C++?. Multiple tools for GetText translation already exist, which would simplify the translation process (not a custom format and editor). See #1389
- Includes correct handling of accented characters (many characters are replaced with (?) symbols). [The tools to do this are not quite completed/working yet.]
- l10n - perform that conversion and do the translations (into English first, and maybe another language to test the system)
- Provide a default hotkey set for each locale? See #692
Attachments (5)
Change History (50)
comment:1 by , 14 years ago
Milestone: | Alpha |
---|
comment:2 by , 14 years ago
Milestone: | → Backlog |
---|---|
Owner: | set to |
comment:3 by , 13 years ago
Owner: | removed |
---|
comment:4 by , 12 years ago
The ticket is very old and in the forum there are many users (including me) who want and are able to translate 0ad to other languages. I hope that this feature comes in a future release soon.
comment:5 by , 12 years ago
As mentioned here: http://www.wildfiregames.com/forum/index.php?showtopic=15072&pid=235820&st=0&#entry235820 translation support isn't likely to come until we reach/get close to the Beta phase. The main reason is that the English text is still subject to a lot of change and thus it's not a wise idea to create a lot of translations which will quickly become outdated. It is better to focus on finishing the features of the game and add translation support once we get closer to having the features of the game (and more importantly the English text) finished. Feel free to explore different solutions and existing libraries. Perhaps you can help translating some other open source project to get experience while you wait for 0 A.D. to add translation support.
comment:6 by , 12 years ago
I'm also a translator of different projects, like Songbird, warzone2100, FreeNAS, unknown-horizons, webmin... But thanks for the hint. I think the game has currently a lot of stable features and should change to the beta phase very soon.
comment:7 by , 12 years ago
Description: | modified (diff) |
---|---|
Type: | task → enhancement |
comment:8 by , 11 years ago
Actually, I think i18n should start as soon as possible in the development cycle. The latter, the harder the process will be.
About l10n, it could start as soon as there is a translator that wants to do it. And I bet, even knowing that translations are likely to need a change soon, many translators will want to contribute right away, as soon as possible.
comment:9 by , 11 years ago
For future reference, this might be a great start point: http://www.wildfiregames.com/forum/index.php?showtopic=13790&st=60#entry257545
comment:10 by , 11 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
Summary: | Localisation → Internationalization |
I’m taking the challenge.
by , 11 years ago
Attachment: | i18n-first-steps.diff added |
---|
Initial implementation which allows translating the main menu of the home page and a couple of other strings in the same page.
comment:11 by , 11 years ago
Changes introduced so far
- BSD-licensed (not mine) implementation of C’s sprintf() function for JavaScript, to be able to translate strings which contain values that change.
- Extended the C++ parser of GUI XML files to support:
- Specifying localizable attributes. Syntax is: <localizableAttribute id="attributeName">Internationalized string</localizableAttribute>.
- Use <keep> and <localize> tags within <action> elements to define what parts of a JavaScript code snipped defined within an XML file can be localized.
- New folder within mods folders: “po”.
- Is meant to contain a POT file (“<modname>.pot”) and PO files for any supported languages (“<languagecode>.<modname>.po”). Following this name convention is mandatory, and necessary to make translations work with the virtual filesystem.
- The patch includes a .po and .pot files as proof of concept and for testing purposes.
- Added a new GPLv2 C++ library, tinygettext. I’ve add it so you can build 0ad using a system-wide version of the library, however, due to changes I performed on the library that I did not send upstream (which I probably should), I advise against it for now.
- Added
source/lib/localization.{cpp,h}
. The Localization singleton takes care of loading the .po files of the virtual file system, as well as detesting the environment language code. Is the bridge between 0ad and tinygettext. - Added a new folder in the root folder,
localization
, which contains:gui.its
, a file that defines the rules to extract strings from the GUI XML files. Used byitstool
.update-pot.sh
, a Bash script that loops through the mod folders, extracts the internationalized strings of each mod (currently it only supports GUI XML files), and generates a POT file in each mod, or updates the existing one.
Translators only need to take the POT file, copy it with a new name following the naming convention described above, and translate. Compiling PO files is not needed, so translators should be able to use their PO files directly from some custom user mod to test their translations as they update them.
To test loading the game translated into Galician in GNU/Linux: LANG=gl && binaries/system/pyrogenesis
. You can find a screenshot here: http://img197.imageshack.us/img197/4715/kwx4.png
comment:12 by , 11 years ago
Keywords: | patch added |
---|---|
Summary: | Internationalization → [PATCH] Internationalization |
comment:13 by , 11 years ago
All right. So, what's better about this implementation over something like...
Current templates have all the unit info in the XML, which is bad for localization:
<Identity> <Civ>athen</Civ> <SelectionGroupName>units/athen_infantry_spearman_b</SelectionGroupName> <GenericName>Athenian Hoplite</GenericName> <SpecificName>Hoplī́tēs Athēnaïkós</SpecificName> <History>Hoplites were the very symbol of Hellenic prestige and citizenship, armed with a spear and a large round bronze-coated shield known as an aspis. Armor was heavy, with bronze helmets and a cuirass of either bronze or linen, in addition to greaves. Hoplites fought in a tight formation called a phalanx, guarding each other with their shields while they attacked the enemy with their 2.5 meter spear or short iron sword.</History> <Icon>units/hele_infantry_spearman.png</Icon> </Identity>
So, in the new template paradigm, we do something like this instead:
<Identity> <Civ>athen</Civ> <SelectionGroupName>units/athen_infantry_spearman_b</SelectionGroupName> <Description>units/athen_infantry_spearman</Description> <Icon>units/hele_infantry_spearman.png</Icon> </Identity>
Where <Description> would call the <GenericName> and <History> information from the "athen_infantry_spearman" line in localized text files, English, German, French whatever.
../localization/units_english.txt
athen_infantry_spearman
GenericName: Athenian Hoplite
SpecificName: Hoplī́tēs Athēnaïkós
History: Hoplites were the very symbol of Hellenic prestige and citizenship, armed with a spear and a large round bronze-coated shield known as an aspis. Armor was heavy, with bronze helmets and a cuirass of either bronze or linen, in addition to greaves. Hoplites fought in a tight formation called a phalanx, guarding each other with their shields while they attacked the enemy with their 2.5 meter spear or short iron sword.
../localization/units_german.txt
athen_infantry_spearman
GenericName: Athenischen Hopliten
SpecificName: Hoplī́tēs Athēnaïkós
History: Hoplites waren das eigentliche Symbol der hellenischen Prestige und Staatsbürgerschaft, mit einem Speer und einem großen runden bronze-beschichteten Schirm als ein aspis bekannt bewaffnet. Rüstung war schwer, mit Bronze Helme und Brustpanzer eines der beiden Bronze-oder Leinen, zusätzlich zu Grieben. Hoplites kämpfte in einer engen Formation namens eine Phalanx, die Bewachung gegenseitig mit ihren Schilden, während sie den Feind angegriffen mit ihren 2,5 Meter Speer oder kurzen Eisen Schwert.
../localization/units_french.txt
PS: I hate how Trac keeps trying to create those inline links to blank Wiki entries. See: GenericName? et al.
comment:14 by , 11 years ago
This implementation does not conflict with your suggestion. Both the current way and the one you suggest should be possible with around the same effort.
However, since I already had to prepare something to deal with the XML of the GUI, your statement, “Current templates have all the unit info in the XML, which is bad for localization”, is not correct. It’s actually the other way around. Preparing the system to extract strings from an XML which is formatted in a i18n-friendly way (that is, text to be translated is a string within a tag, not an attribute, something that your example code complies with) would be trivial, while preparing the system to extract the strings from those .txt files would require a bit of additional effort — not much, but more than with the XML right now.
If moving the strings out of the XML is better from the R&D perspective — if you developers prefer not to have that information in the XML files where it currently is — it’s fine to move it out of the XML files and into those TXT files. However, if you want to do it to make i18n easier, please just don’t.
On a side note, if no one opposes to the approach that the patch implements, would it be possible to submit the patch already? Although the patch is far from complete, it does not break anything, and submitting it already would ensure that further developments do not break it, something that will surely happen (and has happened) if I keep the code to myself. Having to maintain all the changes to myself until the i18n process is complete means I have to deal with conflicts that become more difficult to resolve as the code evolves, and resolving conflicts is specially not funny when you are not too familiar with the codebase.
comment:15 by , 11 years ago
You should fork their repo on github: https://github.com/0ad/0ad
Then work in your own branch and only merge back when you are mostly done. I don't think they'll commit such a WIP patch. I can also lend you a hand if you want.
You should also be aware of the discussion here: http://www.wildfiregames.com/forum/index.php?showtopic=17397
comment:16 by , 11 years ago
I did not know about the Git repo (probably did at some point but forgot about it). I will definitely do it in a Github fork! I will check the forums topic as well.
About lending me a hand, any help is more than welcome, so step in whenever you feel like it :)
comment:17 by , 11 years ago
I’m now working on Github: https://github.com/Gallaecio/0ad
I’ve just added support for Transifex: https://github.com/Gallaecio/0ad/commit/ab566fb1cf64c1fd9f24cfd2d2a5cd07ef8a7d58
- Translators can translate here: https://www.transifex.com/projects/p/0-ad-unofficial/
- Transifex watches the .pot file for changes through Github, so we only need to care about updating it in our repository, Transifex catches up with changes, and automatically updates translation files accordingly.
- I’ve added a new script that automatically downloads new translation files from Transifex, and updates existing ones.
Transifex is just an optional way to handle translations, but it would be possible for specific translation teams to use Git/Subversion directly, or even a different online translation system.
comment:18 by , 11 years ago
So far translating strings from GUI XML and JavaScript files is in place (C++ files as well, but I’m currently focused on finish with the ‘gui’ folder within mod folders).
The next stone in the road are .txt files. As a translator, I don’t want to have a single translation unit that is as long as that of binaries/data/mods/public/gui/manual/intro.txt
. I’m thinking about converting it into an XML file with keep/localize tags for the time being. Any thoughs?
comment:19 by , 11 years ago
It seems the forum is a better place to ask for advice. You get way more comments from the devs there.
I think it's a good idea to eliminate quite useless data formats like this one. Makes life easier in the future. The problem is: This file is read in from javascript code, it seems. So you have to provide javascript with a new function callback to c++ code doing the parsing.
comment:20 by , 11 years ago
That should not be a problem, I’m already calling C++ from JavaScript for localization purposes (localize() function).
The issue here is mainly that the following XML format works for me:
<?xml version="1.0" encoding="UTF-8" ?> <document> <keep>Something not localizable.</keep> <localize>Something localizable.</localize> <keep>Something not localizable.</keep> <localize>Something localizable.</localize> <keep>Something not localizable.</keep> <localize>Something localizable.</localize> </document>
I’m just giving you all an opportunity to provide feedback that prevents me from doing such a thing! :)
comment:21 by , 11 years ago
Computers and programmers don't mind XML, everyone else finds it yucky, and the manual is a file (unlike entity templates) that will be updated frequently and won't have an editing tool.
Why not parse the .txt
files by line, to extract the translatable strings out of them? They are plain text except for some tags, so it shouldn't be hard to translate e.g.:
[font="serif-bold-18"]0 A.D. in-game manual
to
[font="serif-bold-18"]0 A.D. blahblahblah
if it's well formatted (no line breaks in the wrong spots).
I can understand how XML would be easier for implementation, but there's more to consider.
comment:22 by , 11 years ago
OK, I will start by providing single lines for translation, including font tags. However, I’m not happy at all with including font tags in translation units if it can be avoided.
comment:23 by , 11 years ago
Is it really a good idea to impose a particular line structure on the translator? I imagine the placement of words within a sentence or even a paragraph can vary quite a bit from language to language.
comment:24 by , 11 years ago
Each paragraph is a single line. Otherwise, I can use empty lines as a separator instead.
comment:26 by , 11 years ago
Milestone: | Backlog → Alpha 16 |
---|
I think we can have this in master for Alpha 16.
comment:27 by , 11 years ago
Keywords: | review added |
---|---|
Milestone: | Alpha 16 → Alpha 15 |
Owner: | removed |
Status: | assigned → new |
The current status allows proper game translation for any left-to-right language provided that the font game supports all its characters. I think this patch is good enough for master, and any improvement can be done on demand (at translators‘ request) after merging this.
I also need someone in the team to create a Transifex account and let me know his username, so that I can make him manager of the 0 A.D. project there, to handle translation teams and feedback on that platform. Even if you allow me to take care of this myself, we should have one or two additional people with an admin account there, just in case.
So, time for feedback. I’m not sure if I should provide here additional information, or start writing documentation in the wiki. Let me know.
Notes:
by , 11 years ago
Attachment: | internationalization.patch added |
---|
comment:28 by , 11 years ago
I’ve made some changes after the initial feedback. Among other things:
- I’ve renamed folders and code members: Internationalization → I18n, Localization → L10n, localize → translate (when it is string translation, for numbers, dates and such I kept localize as it is more accurate).
- I’ve removed some braces introduces in the GUI code. I tend to use braces even in single-statement ifs, but I see you prefer to avoid them in those cases.
- I’ve added warnings to the special cases in the GUI that handle translating “expected”strings, so that a warning is issue whenever an unexpected string is received.
- I’ve implemented in public/globalscripts/l10n.js some functions for translation caching, to avoid unnecessary calls to the C++ side, which involves string conversions that might prove expensive.
- I’ve rewritten the message extraction and Transifex (translations server) synchronization scripts in Python (instead of Bash).
- For message extraction, I forked a BSD-licensed Python library, babel(.messages), making it work in Python 2 and 3, removing stuff we won’t ever need, and adding features we do need; I called the fork “potter”.
- I also added the GPLv2-licensed Transifex Client (tx) and library (txclib) to the folder, so that whoever performs the translation synchronization does not need a system-wide installation of the client, and wrote a script that uses the library to automatically download translations of the engine and any mod. Note that the Transifex Client only works with Python 2.
- I’ve divided the patch in three (engine, gui, tools). This had been requested, but honestly I just did it because otherwise I would not be able to upload it after the addition of two Python libraries. I hope it helps reviewers nonetheless.
comment:29 by , 11 years ago
Further changes:
- It is no longer necessary to restart the game to get the game language changed.
- There is a script now to generate a special translation file which contains the longest (as in number of characters right now) strings of every existing language; this is intended for UI testing, and should help using the right width when designing the UI elements.
comment:30 by , 11 years ago
Milestone: | Alpha 15 → Alpha 16 |
---|
comment:31 by , 10 years ago
Cc: | added |
---|
comment:32 by , 10 years ago
I rebased Gallaecio's work on a more recent version (see https://github.com/leper/0ad/tree/i18n).
(It compiles fine over here; but running it isn't really working due to a bug with globalscripts, I'll ask Yves about that)
Stuff that is still left to do:
- The lobby/xmpp related additions to gamesetup*.(js|xml) should be reviewed and translated.
- Someone should check if the options menu is working/translated
- GuiInterface GetTimeNotificationText (and messages.js that calls it) needs to be fixed.
- The attack rate display code in selection_details.js
- everything with 'TODO TODO TODO' next to it (mostly checking that it is translated)
- Linking with iconv when glibc provides iconv (added a TODO to extern_libs.lua)
comment:33 by , 10 years ago
Tinygettext needs some work to build in MSVC :( The CMake scripts have issues (not including or importing some files), there is a missing POSIX header, missing defines, and it doesn't have any __declspec
macros to import and export its API symbols. It also has the same problem as gloox, using STL heavily in the API, so we will need a wrapper to mix compiler versions.
It doesn't seem actively maintained either?
comment:34 by , 10 years ago
I've made some quick and dirty fixes, and at least it's possible to compile leper's i18n branch on Windows, tested with VC++ 2008 :) There are quite a few build warnings and as leper hinted, there are also many JS warnings and errors when it runs.
Are there any translations included for a demo? If not, that might be a good idea. I only see English US available as a language on the main menu. Building the translations is just a bunch more steps it seems, so it would be better to have some "prebuilt" for quick testing.
I will clean up my changes, push them to my repo, and submit a pull request or something, rather than explaining them in detail here.
comment:35 by , 10 years ago
The upstream of tinygettext is dead. (It was created and maintained by the devs of SuperTux.) SuperTuxKart is using a slightly modified verision of tinygettext (included in their source tree) with some fixes (spelling, missing headers, fallback on other languages (eg fr_CA depending on fr)) but nothing really major (<15 commits touching those files). (See http://forum.freegamedev.net/viewtopic.php?f=17&t=4920)
I'll see if I can produce a diff for those stk tinygettext changes, but IMO we can just fix it to suit our needs (it isn't too big), and we can ask the stk devs if they'd be happy to create one upstream in the future.
Most of the JS errors should be fixed in r14592, so I'll rebase my git branch again. historic_bruno: You can just commit to my git branch, I gave you access to it. You can download translation files from Transifex (though you might need to create an account for that).
follow-ups: 37 38 comment:36 by , 10 years ago
You can run “source/tools/i18n/pullTranslations.py” to retrieve the latest translations from Transifex. I don’t think it requires an account, but I might be wrong.
comment:37 by , 10 years ago
Replying to Gallaecio:
You can run “source/tools/i18n/pullTranslations.py” to retrieve the latest translations from Transifex. I don’t think it requires an account, but I might be wrong.
Good to know!
I have pushed my commits to fix the Windows build onto leper's i18n branch. The game should build for someone using MSVC (preferably VC++ 2008 to minimize the risk of crashes), though the tinygettext build still needs some work.
leper and I discussed the options and decided maybe it's best to modify tinygettext itself to have a non-STL API, rather than creating a wrapper as Philip did for gloox. It should be less effort and less fragile in the end, we don't really have to worry about upstream conflicts or resistance to our changes.
comment:38 by , 10 years ago
Replying to Gallaecio:
You can run “source/tools/i18n/pullTranslations.py” to retrieve the latest translations from Transifex. I don’t think it requires an account, but I might be wrong.
For reference:
On Windows, I had to install Python setuptools with the instructions here, uncomment line 11 of txclib\web.py
, and add my Transifex credentials to the .transifexrc
in my user directory as described here. Now I have all the latest translations :) Very cool!
comment:39 by , 10 years ago
Someone mentioned in IRC that their Windows build of i18n crashes. Right now that is entirely to be expected, especially if the game is built with anything but VC++2008 in release build, but even then it crashes sometimes (likely due to different compiler flags). That is the symptom of using STL in the tinygettext API, and the solutions are described above (and were discussed at length for gloox and the lobby months ago).
follow-up: 41 comment:40 by , 10 years ago
I've started with the review today. Here are some of the things I've checked today. There are some other things on my list which I haven't posted yet (as you can guess by the ID numbers), but most of them are just things I'd like to check and not real problems. It's planned to discuss and assign the remaining tasks this in this Saturday's meeting.
ID | Title | Description | Type |
4 | tinygettext | Currently linked as static library because it uses STL types in the interface which is not safe when using it as a dynamic library | Note |
25 | Leper Input 5 | everything with 'TODO TODO TODO' next to it (mostly checking that it is translated) | Todo |
34 | L10n.js: use of wrong engine functions | translatePlural, translateWithContext and translatePluralWithContext all call Engine.translateWithContext. Shouldn't they call the respective engine functions? | Bug |
35 | Style: lower case for exported Engine functions | Currently all engine functions (those called like Engine.Function()) start with an upper case letter. Some of the new functions use lower case letters. | Style |
36 | Style: JSInterface_XYZ.{h,cpp} for exported engine functions | The idea is that C++ functions which are exported to JS are declared and defined in a file called JSInterface_XYZ.h/cpp (XYZ being a suitable name). They are also wrapped in a namespace called JSI_XYZ (XYZ being the same name used before for the filename). This namespace also contains the function RegisterScriptFunctions which is responsible for registring these functions to the ScriptInterface. Check JSI_GameView, JSI_Console or JSI_Sound for examples. | Style |
37 | Consider using Map objects for the caching in l10n.js | Check #2475 for details. First we need a decision if we want to use the Map object type and then we should measure if it matters for performance. | Todo |
38 | Currently not localized: printf, fprintf, debug_printf | Do we even want to localize that? Most of that is used for development features and developers are expected to understand English (variable naming, comments etc. are in English). | TBD Feature |
39 | Localizing error/warning messages? | Currently not localized: LOGERROR, LOGMESSAGERENDER, LOGWARNING, LOGMESSAGE Currently localized or partially localized: warn(), error(), log() There's an inconsistency about localizing error and warning messages or not localizing them. Also we have different people who would like to view these types of messages and some of them need localized versions and others need the english versions or other localizations. It would be good to print a localized error message to the user, but we as developers probably don't understand the user's language and need the logs in another language to analyze it. 3 approaches: 1. Don't localize warnings and errors, at least during development. 2. Print in localized form and save two separate log files. One for English and one for the localized version. 3. Store the logs in a raw form and embed a library like jsgettext (http://developer.berlios.de/projects/jsgettext/) in the html logfile (or better include it from there because some users post the logfile as text). After a discussion on IRC we (sanderd17, leper, Yves) tend to the first approach but we'd like to ask Gallaecio for his opinion. | TBD Feature |
40 | Automatic default locale detection broken | If the detection in getConfiguredOrSystemLocale sets the system locale, setCurrentLocale will not call loadDictionaryForCurrentLocale because currentLocale == locale. When using the default contructor without arguments, currentLocale will be initialized with the default locale. ICU documentation for the language parameter of the Locale constructor: âLowercase two-letter or three-letter ISO-639 code. This parameter can instead be an ICU style C locale (e.g. "en_US"), but the other parameters must not be used. This parameter can be NULL; if so, the locale is initialized to match the current default locale. (This is the same as using the default constructor.)â We should change the check if loadDictionaryForCurrentLocale should be called. | Bug |
41 | Country-specific locales broken | loadDictionaryForCurrentLocale searches .po files with currentLocale.getLanguage(). Language is the lowercase two-letter or three-letter ISO-639 code like de and I'm quite sure it won't detect language specific locales like de_CH properly that way. IMO it should work this way: 1. check for an .po file matching language_country (de_CH) and take that if found. 2. check for a .po file matching language (de) and take that if found. 3. fall back to the default untranslated strings | Bug |
42 | tinygettext build warnings | There's a warning when building the tinygettext static library, but it's only due to nbr 55 and can be solved at the same time. | Style |
55 | Logging errors to stderr in log.cpp#L30 | Instead of just commenting out the log output we should add an option for translators to enable it thought the config file. Would probably be nice before Alpha 16 to make translation easier for people who don't compile the game. | Todo |
27 | Atlas localization | Atlas isn't localized yet. | missing feature |
30 | Plural handling | Support for plural handling | Supported feature |
56 | Newlines in textfiles for formatting | There are some messages like this at startup: „tinygettext: Couldn't translate: „ It's caused by the newlines in splashscreen.txt. The newlines are there for formatting purpose and our localization system tries to find a translation for „\n“. | Bug |
57 | Trying to translate already translated template data | GetTechnologyData in session.js calls translateObjectKeys and translates the technology's genericName. Later getEntityNames in utility_functions.js tries to translate it again and fails because it passes the already translated string as msgid. Steps to reproduce (I've used the German translation): 1. Enable translation error logging in Log.cpp 2. Singleplayer->Matches 3. keep the default setup, just set your civ to Iberians 4. Start the game and then select a female citizen I'm getting the message „tinygettext: Couldn't translate: Stadtphase“ | Bug |
58 | Strings not yet added for translation | Also check nbr 59 in regard to the simulation localization - simulation/components/BuildRestrictions.js (multiple strings) - simulation/components/Player.js („Insufficient resources“) - Gui/session/messages.js ("You have been attacked by %(attacker)s!") - ... others? | Todo |
59 | Localization of components | How do we localize strings coming from components? These can be sent over the network as messages or be part of the simulation state (and must therefore not differ). Localization should most likely be deferred to the GUI code. | Question |
15 | Mentioning contributors | Apparently all (?) contributors of translations are mentioned in the .po file. Is this sufficient and what if they are compiled (to binary files) for the release? Is it OK to list their email addresses there and distribute them as part of the 0 A.D. download? How do other services handle that if we don't stick to Transifex? | Administrative |
comment:41 by , 10 years ago
Replying to Yves:
58 Strings not yet added for translation Also check nbr 59 in regard to the simulation localization
- simulation/components/BuildRestrictions.js (multiple strings)
- simulation/components/Player.js („Insufficient resources“)
- Gui/session/messages.js ("You have been attacked by %(attacker)s!")
- ... others?Todo
+ headers in lobby lists (map lists, player lists ...)
comment:42 by , 10 years ago
Priority: | Should Have → Release Blocker |
---|
comment:43 by , 10 years ago
Open issues are now tracked on github until it's committed and will not be updated here.
comment:45 by , 10 years ago
Keywords: | review removed |
---|
Milestone Alpha deleted