Search the Community
Showing results for tags 'Translation'.
-
The Big Question A. How would you call the population limit of a specific player that can be extended during a game? B. How would you call the population limit of any player that cannot be extended during a game? Rules: The answer for A and B must be different. Feel free to provide multiple answers. Generally, the fewer and shorter the words, the better. Extra points if your choice for A cannot be misunderstood for B, your choice for B cannot misunderstood for A, and none of your choices can be misunderstood for a different concept (e.g. the sum of the A or B limits of all players during a game, or the maximum B limit of 0 A.D. itself). Explain! Explain! I’ve recently started working on an English Style Guide for 0 A.D. The goal is to provide developers with guidelines to follow when writting user-facing texts, so that game texts gain consistency providing a slightly better experience for players and a significantly better experience for translators. So I am reviewing translator reports about English strings, and trying to build the English Style Guide as I improve the affected English strings. I believe some of the core principles of English style guides for software are: Use unambiguous words to refer to a concept. Always the same words to refer to the same concept. Never use the same words to refer to two different concepts. And there is one clear case where the current texts of 0 A.D. break all of these rules: the population limit. (Thanks to @GunChleoc for bringing it up on Transifex) See, 0 A.D. does not have a single population limit. We have two different population limits: A. The population limit of a specific player during a game, that can be extended by building houses, researching technologies, and so on. B. The population limit of any player during a specific game, the one that no player can surpass regardless of houses built, technologies researched, and so on. And the terminology that we use in 0 A.D. to refer to them is often ambiguous, with different words used in different parts of the game, and with the same words use to refer to both types of population limit in different parts of the game. Used words include: population limit, population cap, maximum population, maximum population limit. So I wish your feedback in finding the right terminology to handle these concepts in the game texts. I propose to keep this topic open until someone proposes a clear winner or, if there is no clear winner some time from now, to create a poll to choose one. I would rather not rush the choice, but I wish to have this settled by the time I finish dealing with the rest of the issues raised by translators on Transifex (in maybe a few months). Advice Be creative. Check what other similar games use. Have a thesaurus at hand.
- 21 replies
-
- 4
-
- translation
- english style guide
-
(and 1 more)
Tagged with:
-
I just lost hours of my work on another project, so I guess a big warning is in order. Transifex has a new "feature" that if you correct some strings offline and then upload, Transifex will silently ignore your changes. At least with translator permissions, I haven't checked yet if this also happened with reviewer permissions. Already reviewed strings are now completely impossible to correct offline - at least the upload window will inform our about that one. I already contacted Transifex about the issue.
-
We had discussed with sanderd17 yesterday at IRC, that we can't show how much work translator did. So I have created the small tool to take statistics from transifex. And fcxSanya suggested to share the tool on the forum. Link: https://github.com/vladislavbelov/transifex-stats/ Usage: python transifex-stats.py -i 0ad -u vladislavbelov -l ru This command produce file with next content: http://pastebin.com/jbW6xQTW Instead of vladislavbelov & ru you could paste your username on the transifex and language code.
-
Hi again. Localization became a topic again today and after some extensive feedback from Michael and his vision of things I decided to write a quick prototype of the system. 1) Language files The system should be simple and allow easy modification of game strings. Localization strings should be placed into simple .txt files and the first part of the file name marks the language used, while the rest of the file name is ignored: -) Format: {lang}xxxxx.txt -) Example: english_units.txt All files associated with a language will be collated into a single language dictionary. 2) File format Since the files are simple text files, the format should also be simple, easy to edit and foremost it should be readable. Each translation entry (id string from now on) is described first by its id string on a single line, followed by its attribute values, each on a single line. Each attribute is followed by a translation string, separated with white-space. An id string entry is terminated by an empty line. For the sake of parsing correctness, any empty lines should be ignored. Lines can be commented using a semicolon ;. -) Format: -) Example: 3) Current translation text Now of course, the first concern of Michael was how to get all the current translations from XML to new files. It took a few minutes of scribbling to put together a tiny conversion tool. It simply shuffles through a set of sub-directories and collates xml files of a directory into a file. using System.Xml;using System.IO;namespace WFGLocalizationConverter{class Program{static string GetValue(XmlNode node, string key){if (node == null || (node = node[key]) == null)return null;return node.InnerText;}static void CreateTranslationFile(string path){string[] files = Directory.GetFiles(path, "*.xml", SearchOption.TopDirectoryOnly);if (files.Length == 0)return; // nothing to do hereStreamWriter outfile = new StreamWriter(string.Format("english_{0}.txt", Path.GetFileName(path)));outfile.WriteLine(";; Generated by WFGLocalizationConverter\n");foreach (string file in files){XmlDocument doc = new XmlDocument();doc.Load(file);XmlNode identity = doc["Entity"]["Identity"];if (identity == null)continue; // not all entities have <Identity> tagsstring generic = GetValue(identity, "GenericName");string specific = GetValue(identity, "SpecificName");string tooltip = GetValue(identity, "Tooltip");string history = GetValue(identity, "History");if (generic == null && specific == null && tooltip == null && history == null)continue; // no useful data for us// write it downoutfile.WriteLine(Path.GetFileNameWithoutExtension(file));if (generic != null) outfile.WriteLine("generic {0}", generic);if (specific != null) outfile.WriteLine("specific {0}", specific);if (tooltip != null) outfile.WriteLine("tooltip {0}", tooltip);if (history != null) outfile.WriteLine("history {0}", history);outfile.WriteLine();}outfile.Close(); // clean-up & flush}static void Main(string[] args){foreach(string path in Directory.GetDirectories("data/"))CreateTranslationFile(path);}}} Running this tiny piece on "simulation emplates\", I get a full list of collated translation files: english_campaigns.txtenglish_gaia.txtenglish_other.txtenglish_rubble.txtenglish_special.txtenglish_structures.txtenglish_units.txt 4) Loading translation files Now that we've converted all of this into the language files, we need to read it back in C++. In order to minimize memory usage, we load the entire file into a buffer, treat it as a string and tokenize it. The tokenized strings are then put into a hash map (std::unordered_map<size_t, TEntry>). Even though a sorted vector indexed with binary search would be more memory efficient, we resort to the hashmap for simplicity. The code itself is written as a small C/C++ module (yeah, sorry - it's 175 lines): #include <stdio.h> // FILE* suits us a bit better in this case#include <unordered_map> // lazy today// good old k33 hashinline size_t hash_k33(const char* str){size_t hash = 5381;while(int c = *str++)hash = ((hash << 5) + hash) + c; // hash * 33 + creturn hash;}// tests if the range is ALL-whitespaceinline bool is_whitespace(const char* begin, const char* end){while(begin < end) {if(*begin != ' ' && *begin != ' ') return false; // found a non-ws char++begin;}return true; // this is all whitespace}// advances to the next lineinline char* next_line(char* str){return (str = strchr(str, '\n')) ? ++str : nullptr;}// reads a valid line (skipping comments and empty lines)const char* read_line(char*& str){char* line = str;do{if(*line == ';' || *line == '\n' || *line == '\r')continue; // next linechar* end = strpbrk(line, "\r\n"); // seek to end of lineif(is_whitespace(line, end)) // is it all whitespace line?continue; // skip line// window CR+LF ? +2 chars : +1 charstr = *end == '\r' ? end + 2 : end + 1; // writeout ptr to next line*end = '\0'; // null term this line, turning it into a C-stringreturn line;} while(line = next_line(line));return nullptr; // no more lines}// gets an attribute lengthinline int attr_len(int attrid){static size_t attrlens[] = { 0, 7, 8, 7, 7 };return attrlens[attrid];}// gets the attribute id [1..4] of this line; 0 if not an attributeint attr_id(const char* line){static const char* attributes[] = { 0, "generic", "specific", "tooltip", "history" };for(int i = 1; i <= 4; i++) {size_t len = attr_len(i);if(memcmp(line, attributes[i], len) == 0) { // startsWith matchconst char* end = line + len;if(*end != ' ' && *end != ' ') return 0; // it's not a valid attribute!return i; // it's a valid attribute}}return 0; // it's not a valid attribute}// UTF8 Translation Entrystruct TEntry{const char* idstring; // id string of the translation entryconst char* generic; // 'generic' attribute stringconst char* specific; // 'specific' attribute stringconst char* tooltip; // 'tooltip' attribute stringconst char* history; // 'history' attribute stringvoid set(int attrid, const char* line){line += attr_len(attrid) + 1; // skip keyword +1 charwhile(*line == ' ' || *line == ' ') ++line; // skip any additional whitespace*((const char**)this + attrid) = line; // hack}};// UTF8 dictionarystruct Dictionary{char* mBuffer; // buffersize_t mSize; // buffer sizestd::unordered_map<size_t, TEntry> mEntries;Dictionary(FILE* f){// get the file sizefseek(f, 0, SEEK_END); size_t fsize = ftell(f); fseek(f, 0, SEEK_SET);char* str = mBuffer = new char[mSize = fsize];// read all the data in one gofread(mBuffer, fsize, 1, f);const char* line = read_line(str);if(line) do {TEntry entry = { 0 };if(attr_id(line) == 0) { // not an attribute; great!entry.idstring = line;int attrid;while((line = read_line(str)) && (attrid = attr_id(line)))entry.set(attrid, line);// emplace entry into the hash table:mEntries[hash_k33(entry.idstring)] = entry;}} while(line);}~Dictionary(){delete mBuffer, mBuffer = nullptr;mEntries.clear();}inline const TEntry* at(const char* idstring) const { return &mEntries.at(hash_k33(idstring)); }inline const TEntry* operator[](const char* idstring) const { return &mEntries.at(hash_k33(idstring)); }inline const TEntry* at(size_t idhash) const { return &mEntries.at(idhash); }inline const TEntry* operator[](size_t idhash) const { return &mEntries.at(idhash); }};struct Entity{const TEntry* descr;// ...Entity(const TEntry* descr) : descr(descr) {}void Print() // print the unit{printf("%s\n", descr->idstring);if(descr->generic) printf("generic %s\n", descr->generic);if(descr->specific)printf("specific %s\n", descr->specific);if(descr->tooltip) printf("tooltip %s\n", descr->tooltip);if(descr->history) printf("history %s\n", descr->history);printf("\n");}};int main(){if(FILE* f = fopen("english_gaia.txt", "rb")){Dictionary english(f);fclose(f);Entity(english["fauna_bear"]).Print();Entity(english["flora_bush_badlands"]).Print();system("pause");}return 0;} ----------- I'll put the main focus on how the Dictionary is actually used. For any given entity, we will assign a Translation entry which contains all the required strings we need. These Translation entries can be retrieved from the dictionary by their id string or its hash. This is done only once when the Entity type is instantiated. Here's a snippet of this in action: struct Entity{const TEntry* descr;// ...Entity(const TEntry* descr) : descr(descr) {}void Print() // print the unit{printf("%s\n", descr->idstring);if(descr->generic) printf("generic %s\n", descr->generic);if(descr->specific)printf("specific %s\n", descr->specific);if(descr->tooltip) printf("tooltip %s\n", descr->tooltip);if(descr->history) printf("history %s\n", descr->history);printf("\n");}};int main(){if(FILE* f = fopen("english_gaia.txt", "rb")){Dictionary english(f);Entity(english["fauna_bear"]).Print();Entity(english["flora_bush_badlands"]).Print();system("pause");}return 0;}And its output in the console: fauna_bearspecific Bearflora_bush_badlandsspecific Hardy Bushhistory A bush commonly found in dry flatlands and rocky crags.This is it for now. What you should do now is discuss! You can take a look at the converted translation files below. Regards, - RedFox english_campaigns.txt english_gaia.txt english_other.txt english_rubble.txt english_special.txt english_structures.txt english_units.txt
-
the request is to translate website content for play0ad.com, and that this has a version in Spanish, i don't know if is possibly do this as we are doing with the game through some similar to Transifex platform and also help translate the Wikipedia article or Update to last english versión. la solicitud es para traducir contenido de la página web play0ad.com, y que esta tenga una versión en español, no se sí se podrá hacer igual que estamos haciendo con el juego mediante alguna plataforma similar a transifex , y que también ayuden a traducir el artículo de Wikipedia. With Wikipedia Sanderd17 ask help with that, but I was can't with that.
- 4 replies
-
- 1
-
- translation
- update
-
(and 3 more)
Tagged with:
-
EDIT: Use https://github.com/leper/0ad/tree/i18n. As some people have started trying to build the internationalization branch (patch against the Subversion trunk), Ive not gotten a single report of anyone having successfully built it. In fact, people have reported issues on both Linux and Windows, which worries me. I would like to keep track of the known issues here, and try to fix them one by one until the internationalization branch not only allows to run the game in any language, but in any machine as well. These are the known issues: (FIXED) In Windows, ICU must be added to the libraries folder for Windows. IconV, a dependency of ICU, might be required as well.(FIXED) In source/i18n/L10n.cpp, the line #include "precompiled.h" is missing (it appears in every cpp source file).(IN PROGRESS) In Linux, tinygettext is not automatically compiled. When making the program, -ltinygettext cannot be found, I have to run myself build.sh in libraries/source/tinygettext to make it work.In Linux, it is not possible to lauch the game, as it gets core dumped.(IN PROGRESS) In Windows, tinygettext must be built for Windows and binaries must be included.For tinygettext built with a compiler to be compatible with the game being built with a different compiler, we cannot use std::string, but a wrapper as in https://github.com/JoshuaJB/0ad/blob/lobby/source/lobby/glooxwrapper/glooxwrapper.h#L107In Linux, the tinygettext build script does not have execution permissions.If you are aware of any issue building or running the internationalization branch that is not listed here yet, please let me know. If you succeeded on building and running the internationalization branch, please let me know as well. In both cases, I would really appreciate it if you could provide some details (operating system name and version and build tools mainly).
-
translation temporary solution for o problem with lines with "%".
anfialro posted a topic in Bug reports
Hi! I have one temporary solution for o problem with lines with "%". In some cases it's necessary the "+" with number. Example: +25%. In other cases add a next letter of english translation. Example: Line 338 English +25% health for spear infantry, but also +10% train time. Portuguese +25% h de saúde para os lanceiros mas também +10% t em tempo de recrutamento. And other problem is ⏎ English: Line 2711 Classes: Hero Healer.⏎ Hero Special: "Healer" - Heal units at an accelerated rate.⏎ Hero Special: "Teacher" - Empower a building to research and train +50% faster.⏎ Hero Special: "Philosopher" - Research 4 special technologies only available to Chanakya. Resolved in portuguese: Categoria: Herói sacerdote. Habilidade especial de herói: Médico - Cura todas as unidades rapidamente. Habilidade especial de herói: Professor - Guarnece num edifício para investigar e recruta 50% f mais rápido. Habilidade especial de herói: Filósofo - Investiga 4 tecnologias especiais só disponíveis para Kautilya. In my opinion, one definity solution is in english eliminate all "%" and writing "100 Percent". The problem with "&" it's: http://php.net/manual/en/function.sprintf.php Regards, André Rodrigues -
I thought I better make an obvious topic for this rather than continuing to report in the French language thread. I think these need separating, since they're both the generic and the specific name. BrasidasChandragupta MauryaThere might be more.
-
Hello, I appreciate 0ad and I started the French translation since r11863. To date, the r13878 is finished (with some details). By maximum 2 days (time to upgrade to r13872), I wanted to share it on launchpad for a return of French players, but ... with only public-en.zip (or update-en.zip) placed in /mods/public/, I bug to transmit these files to launchpad (the deb. works fine locally). Someone could help me to create the first package (rules, source.change ...) ? Thank you, Loki72
-
I decided to start working on image internationalization and localization. This is mostly important for those languages that translate game names, however, any image might need to be somehow modified for a certain locale. The approach I plan to follow is that of The Battle for Wesnoth. In The Battle for Wesnoth, any image can be translated. When the game loads an image, it first checks if within the folder where the image is there is a localization folder with a localized version of that image for the current locale. For example, if the current locale is "gl", and you have a file in "folder/image.png" and a localized version in "folder/localization/gl/image.png", when the game is required to load "folder/image.png" it first checks if "folder/localization/gl/image.png" exists, and since it does exist, it loads "folder/localization/gl/image.png" instead of "folder/image.png". Simple To help translators to keep images up to date, they have a system which basically generates checksums of translated and original images, and if developers update an original image, translators can check in a file that the original image was modified after they localized it the last time, so they know they might need to update the localized image. Another important part of the image localization is explaining to translators how to localize specific types of images. It is important to supply translator with either source versions (for example, in Gimp format) of images, or with detailed steps to generate certain images from scratch. Here is where there is not much I can do, and I need your help. Can anyone point me to an editable version of "public/art/textures/ui/pregame/shell/logo/0ad_logo.png", "public/art/textures/ui/pregame/shell/logo/fundraiserlogo.png" and "public/art/textures/ui/pregame/shell/logo/product.dds" if there is one? What font are we using for "A.D." in "0 A.D." or for "Empires Ascendant"? How are DDS images compressed? (if I save a version modified with Gimp uncompressed it takes 3 times as much space as the original one).
- 3 replies
-
- 1
-
- localization
- internationalization
-
(and 1 more)
Tagged with:
-
Currently, unit template files have a translatable field called Tooltip. This field, as far as I’ve seen, may contain the following information: • Unit classes (recently prefixed by ‘Classes:’). • Units that this unit counters (prefixed by ‘Counters:’). • Units that counter this unit (prefixed by ‘Countered by:’). • Unit description. In the XML, these are differenciated by line breaks. What would you think about providing separated fields for each one of these? • DisplayClasses (as opposed to the class names used in the game logic) • Counters • CounteredBy • Description Pros would be: • Easier to keep consistency between tooltips. • Ability to use a different font or text style on different elements. • Ability to reorder the elements in the interface easily, without changing all XML files, nor affecting translations. • Ability to show a different combination of these bits of information in different contexts. • Easier for translator, as they would only need to translate the "Prefix: <data>" strings once, and the rest of the strings will have a decreased size. And I honestly cannot think of cons here. Also, if you agree, should I let you do this yourselves in master, or should I do this myself in my i18n branch? Or should I maybe write a patch against master only for this?
- 11 replies
-
- internationalization
- localization
-
(and 4 more)
Tagged with: