Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ International ➜ Localization - is it needed?

Localization - is it needed?

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1 2  

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Sun 08 Apr 2007 06:42 AM (UTC)
Message
Now that the source for MUSHclient is available, maybe someone wants to tackle localizing it for a different language. Hopefully this would be done in such a way that a single version could still exist, rather than lots of concurrent ones.

It is a daunting task, and quite possibly not worth it. I would be interested to know if any users of MUSHclient, who speak languages other than English, would find it useful?

Things that could be changed would be:


  • Menus - this is probably quite easy, and I think Windows supports multiple menus for different languages, inside a single executable.

  • Dialog boxes - there are quite a few of these, but redoing them in another language would probably only take a few days.

  • Error alerts - these are generated programatically usually, but it wouldn't be too hard to find them and make language-dependent versions.

  • General strings - this is probably the biggest job. There are lots of places where things like "22 aliases" are generated. A translation would need to convert the words, and handle things like singlur/plural.

  • Configuration items. For example, if you copy a trigger to the clipboard, you see something like this:

    
    <triggers>
      <trigger
       custom_colour="2"
       enabled="y"
       group="eat_drink"
       match="You are thirsty."
       name="thirst_trigger"
       sequence="100"
      >
      <send>get flask bag
    drink flask
    put flask bag</send>
      </trigger>
    </triggers>
    


    Would it make any sense to try to translate all of that?


I would be interested to know what other users think. Do players whose first language is something else (eg. Greek) simply learn enough English to understand the menus? Or what? I am curious.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #1 on Sun 08 Apr 2007 06:47 AM (UTC)
Message
Another large can of worms is the Unicode issue. To support many languages internal strings would need to be in Unicode, whereas the application is currently not a Unicode application.

It would either need to be converted - somehow - or the relevant strings stored as UTF-8 and then displayed in Unicode at the last moment.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Hairui   China  (24 posts)  Bio
Date Reply #2 on Sat 09 Jun 2007 07:33 AM (UTC)

Amended on Sat 09 Jun 2007 07:34 AM (UTC) by Hairui

Message
In fact, I know someone has tried the localization work in a hard way, maybe by modifying the executable file 's resource(mushclient.exe) through a tools such as VC++.

There is a picture of the localized Mushclient on the following url :http://mc.cacn.net/help.php?cat=47&scat=11

For us who use asian languages as first language, the localization is needed certainly.

And if the localization is placed on the agenda, I hope the way is supplying a external text file including the text of the GUI. Which is to say, to localize the MushClient, the only thing need to be done is translating the text in the external file.

Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #3 on Sat 09 Jun 2007 08:24 AM (UTC)
Message
That is certainly a very impressive effort. :)

As I mentioned earlier, there are major places you can localize:


  • In the resource file - this is dialog boxes mainly - where you could change the labels of the various boxes.

    If someone wanted to produce a localized version of that, it could probably be incorporated into the standard distribution where, hopefully, the correct one would be selected automatically.

  • Built-in strings. This is stuff like error messages like "could not connect". Currently these are hard-coded. It would be quite an effort to change those to strings from a file. This is also because a lot of these are not just a simple message, but have imbedded variables, such as "File x cannot be opened because of y".

    They may also have provision for things like multiples. (eg. "1 trigger", "2 triggers" - note the "s")


Probably a good start would be to make a localized resource file - after that we could take it from there.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #4 on Sat 09 Jun 2007 12:10 PM (UTC)
Message
The general idea is great and I am sure that Mushclient has enough non-English speaking users to do the job. I personally would love to help with the Russian translation.

So here are my thoughts on it.

1) Translating the resource files shouldn't be that big of a problem, though I haven't figured out how to make VS 2003 show Russian text instead of question marks which it shows right now.

2) There's no point in translating the XML in settings. I've never seen any applications that used XML in any language other than English. This sort of translation would be pretty useless and would actually look bizarre to the users.

3) Translating the literal strings in the source files will result in the need to compile a separate version of the app for each supported language. Or am I wrong?

4) If I am correct on point 3 then this scheme will be quite awkward for both the users and translators. Especially for the latter, as each new version that introduces any changes in UI text will have to be re-scanned for strings, re-translated and re-compiled. Additionally, each translator would need to maintain his own version of the source code.

5) I've personally only ever used a single method of localizing software. That method was based on gettext (http://www.gnu.org/software/gettext/) and I have to say that I liked it.

One big advantage of gettext is that it allows to search and edit the source code to make it suitable for translation only once. Then it produces a set of files with translatable strings (one file for each language) and from there on translators can work on these files, which can be kept under source control together with the main code, or separately so that translators can mirror and update them locally without messing with the source code.

When adding new strings to the source, all one needs to do is mark them as "translatable" - this is commonly done with a _(String) macro, so such a string is simply _("Translate this please.")

Translation files are then compiled by gettext, and are used during runtime to pull out the version of the string that corresponds to the locale chosen by the user, or glimpsed from system settings somehow.

So basically, my suggestion is to look into the possibility of amending Mushclient's source to use gettext (or some similar localization scheme).

Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #5 on Sat 09 Jun 2007 09:34 PM (UTC)

Amended on Sat 09 Jun 2007 11:36 PM (UTC) by Nick Gammon

Message
One of the reasons for original the post was to gauge the level of interest. Clearly quite a bit of work would be involved, and I didn't want to start if no-one was interested.

I am a little surprised from the earlier post that the Asian version worked as well as it did. MUSHclient is not compiled as a Unicode application, however they appeared to get the dialog boxes to appear in Unicode. How this works, I am not sure, and any advice from the people who did that would be welcome.

I have read the gettext documentation a bit, and I see where they are heading. One thing I am interested to know, is whether operating system calls like AfxMessageBox will successfully translate Unicode (or UTF-8) sequences. For example, from the source:


    ::AfxMessageBox (CFormat ("Unable to create TCP/IP socket for \"%s\", code = %i (%s)", 
                    (const char *) m_mush_name, 
                    iStatus,
                    GetSocketError (iStatus)));


Now assuming the message itself was translated, would it appear correctly or as gibberish?

If as gibberish, then I might have to write my own AfxMessageBox function that recognises UTF-8 strings.

If someone (eg. Ked) has access to a compiler and runs a non-English character set, perhaps they can test that for me.

Even a simple message like this should test it:


      ::AfxMessageBox ("Insufficient memory in buffer to decompress text", MB_ICONEXCLAMATION);


... assuming you do a Russian version, and that it uses UTF-8 sequences.

I am presuming that we would not attempt to translate things like:


  • Colour names (eg. "darkred")
  • XML keywords (eg. "<triggers>")
  • MUSHclient configuration options (eg. "other_text_colour")
  • Lua or any other script language syntax
  • Script function names (eg. world.Note)


An interesting problem case is this code:


  dlg.m_strPasteMessage.Format ("About to send: %ld character%s, %ld line%s to %s.",
                                nLength,
                                nLength == 1 ? "" : "s",
                                nLines,
                                nLines == 1 ? "" : "s",
                                (LPCTSTR) m_mush_name);


Note the careful work I have gone to here to add "s" to plurals. This sort of thing would have to be reworked, as I presume that some languages do not change in the plural form, and if they do change, it won't be by adding an "s".

Quote:

3) Translating the literal strings in the source files will result in the need to compile a separate version of the app for each supported language. Or am I wrong?


Not according to the gettext documentation. Take this line for example:


    ::AfxMessageBox ("An error occurred calculating amount to send to world", 
                      MB_ICONEXCLAMATION);


I gather it changes to:


    ::AfxMessageBox ( _("An error occurred calculating amount to send to world"), 
                      MB_ICONEXCLAMATION);


... where we use this define:


#define _(String) gettext (String)


Now, using one piece of source, at runtime the gettext function looks up "An error occurred calculating amount to send to world" in a translation file, and find the appropriate string to replace it with (based on the current language environment), and the replacement string is displayed.

From what I have read, part of the translation file includes the C source name and line number, although I am not certain why this is required.




Perhaps I could start with a pilot project - one that simply translates a small subset of messages. That would at least be a proof of concept. For example, the "welcome to MUSHclient" message that appears in the output window, and the message that appears when you can't connect to a world.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #6 on Sat 09 Jun 2007 10:43 PM (UTC)

Amended on Sat 09 Jun 2007 10:44 PM (UTC) by Nick Gammon

Message
Just a bit of explanation about how this gettext stuff works (for my benefit too).


  • We start by adding a define to the top of the source file:


    #define _(String) gettext(String)


  • Then we go through the source changing:

    
    "some string to be translated"
    
    to
    
    _("some string to be translated")
    


    This indicates that the target string should be converted.

    (this is the lengthy and tedious bit, of course)


  • Then we extract the strings, like this:

    
     xgettext  -k_ -o mushclient.pot (list of files)
    


    This gives a file looking like this:

    
    # SOME DESCRIPTIVE TITLE.
    # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
    # This file is distributed under the same license as the PACKAGE package.
    # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
    #
    #, fuzzy
    msgid ""
    msgstr ""
    "Project-Id-Version: PACKAGE VERSION\n"
    "POT-Creation-Date: 2007-06-10 08:35+1000\n"
    "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    "Language-Team: LANGUAGE <LL@li.org>\n"
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=CHARSET\n"
    "Content-Transfer-Encoding: 8bit\n"
    
    #: mainfrm.cpp:221
    msgid "Failed to create MDI Frame Window"
    msgstr ""
    
    #: mainfrm.cpp:230
    msgid "Failed to create toolbar"
    msgstr ""
    
    #: mainfrm.cpp:240
    msgid "Failed to create status bar"
    msgstr ""
    
    #: mainfrm.cpp:250
    msgid "Failed to create game toolbar"
    msgstr ""
    
    #: mainfrm.cpp:260
    msgid "Failed to create activity toolbar"
    msgstr ""
    
    #: mainfrm.cpp:724
    msgid "(No world active)"
    msgstr ""
    
    #: mainfrm.cpp:1138
    msgid "Unable to open the Gammon Software Solutions web page: "
    msgstr ""
    
    #: mainfrm.cpp:1148 mainfrm.cpp:1157
    msgid "Unable to open the MUSHclient forum web page: "
    msgstr ""
    
    #: mainfrm.cpp:1182
    msgid "Unable to open the MUD lists web page: "
    msgstr ""
    
    #: mainfrm.cpp:1337
    msgid "Unable to open the Gammon Software Solutions Bug Report web page: "
    msgstr ""
    
    #: mainfrm.cpp:1565
    msgid "Inactive world"
    msgstr ""
    
    #: mainfrm.cpp:1629
    msgid "World or text files (*.mcl;*.txt)|*.mcl;*.txt|All files (*.*)|*.*||"
    msgstr ""
    
    #: mainfrm.cpp:1634
    msgid "World files (*.mcl)|*.mcl|All files (*.*)|*.*||"
    msgstr ""
    
    #: mainfrm.cpp:1778
    msgid "Unable to open the MUSHclient documentation web page: "
    msgstr ""
    
    #: mainfrm.cpp:1788
    msgid "Unable to open the regular expressions web page: "
    msgstr ""
    
    #: mainfrm.cpp:2136
    msgid "Unable to open the plugins web page: "
    msgstr ""
    


  • We copy that file to something like DE.po (for the German version)

  • We edit that file, changing each message by substituting a new translation at the 'msgstr ""' line.

    (this is also a tedious part)

  • We get MUSHclient to recognise the current locale and process the correct file (I haven't got that far yet).



- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #7 on Sat 09 Jun 2007 11:41 PM (UTC)
Message
I bit more reading of the gettext documentation indicates that the plural form is even more complex than I realised. In some languages, apparently there are even more than 2 forms. Conceptually it is similar to English ordinal numbers, eg.


1st      -- form A
2nd      -- form B
3rd      -- form C
4th      -- form D
5th      -- form D again
21st     -- form A again
22nd     -- form B again


Also apparently some languages have a different syntax for zero of something (eg. 0 dogs, 1 dog, 2 dogs ... would be 3 different forms in some languages).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #8 on Sun 10 Jun 2007 01:03 AM (UTC)

Amended on Sun 10 Jun 2007 01:05 AM (UTC) by Nick Gammon

Message
A quick scan of the source shows there are around 321 calls to AfxMessageBox - so that is around 321 warning or information messages that need translation.

Some of them (perhaps half) are parametized, which adds the complexity of handling the parameter(s). For example:


"Replace your typing of (something) with (something else)?"


Or:


"1 trigger, 2 aliases imported"


On top of that would be other messages, like:


"Welcome to MUSHclient version 4.06!"


And, script error messages:


Compile error
World: (world name here)
Immediate execution
(nature of error here)


Then there are things like the list of plugins, where the column headings are hard-coded into the code:


 m_ctlPluginList.InsertColumn(eColumnName, "Name", LVCFMT_LEFT, iColWidth [eColumnName]);
 m_ctlPluginList.InsertColumn(eColumnPurpose, "Purpose", LVCFMT_LEFT, iColWidth [eColumnPurpose]);
 m_ctlPluginList.InsertColumn(eColumnAuthor, "Author", LVCFMT_LEFT, iColWidth [eColumnAuthor]);
 m_ctlPluginList.InsertColumn(eColumnLanguage, "Language", LVCFMT_LEFT, iColWidth [eColumnLanguage]);
 m_ctlPluginList.InsertColumn(eColumnFile, "File", LVCFMT_LEFT, iColWidth [eColumnFile]);


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Ked   Russia  (524 posts)  Bio
Date Reply #9 on Sun 10 Jun 2007 11:27 AM (UTC)
Message
I've performed a couple of simple tests of the Unicode issue.

I've found that trying to use Unicode with any of the early versions of VS is probably hopeless. At least VS.NET (ver. 7) failed to render Russian text properly no matter what settings I changed and what codepages I selected. Some googling had revealed that VS2005 (ver. 8) does support Unicode more or less properly, so that's what I was using for testing.

Firstly, I've managed to fix the problem with menus in the resource file that I've already mentioned earlier - Russian characters that I enter in the properties window are replaced with question marks both in the design view and during runtime. This was in VS.NET. The fix in VS2005 wasn't immediately obvious either: I had to close the solution, open the RC as a separate file, edit it to replace the English text with Russian, and save it as Unicode. After that I was able to compile the solution and all characters were properly displayed during execution.

Secondly, I've tested the AfxMessageBox callback. I haven't hooked up gettext yet, so what I did was also - save the individual source file (doc.cpp) in Unicode and edit one of the messages:

//strMsg.Format ("Unable to resolve host name for \"%s\", code = %i (%s)", 
	  strMsg.Format ("&#1053;&#1077;&#1074;&#1086;&#1079;&#1084;&#1086;&#1078;&#1085;&#1086; &#1085;&#1072;&#1081;&#1090;&#1080; &#1072;&#1076;&#1088;&#1077;&#1089; \"%s\", &#1082;&#1086;&#1076; = %i (%s)",
                      (const char *) strWhich,
                      WSAGETASYNCERROR (lParam),
                      GetSocketError (WSAGETASYNCERROR (lParam)));
      if (App.m_bErrorNotificationToOutputWindow)
        Note (strMsg);
      else
        ::AfxMessageBox (strMsg);


This message was also properly displayed. So, at least with VS2005, Unicode can be used without too much trouble.
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #10 on Sun 10 Jun 2007 08:52 PM (UTC)
Message
I'm a bit puzzled it was that easy - this was in the full MUSHclient compile?

MUSHclient isn't a Unicode application and probably cannot be made one now without heaps of work.

The normal AfxMessageBox function (in a non-Unicode application) expects 8-bit data.

I have made a workaround by making a helper function that calls MessageBoxW (not AfxMessageBox), with UTF-8 data being supplied to the function. First it converts it ti 16-bit Unicode, and then calls MessageBoxW with that.

This seems to work on XP - on my copy of NT at least, the system font didn't support the characters I tested.

As for changing things like dialog boxes - do you think you could make a copy of the resources that use Russian characters, and I could merge them into the existing source? I don't have the .NET compiler (yet, anyway).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #11 on Mon 11 Jun 2007 02:05 AM (UTC)
Message
Well I am making some progress with localization. Before I go any further I am interested to see what the default locale is for various users.

Can anyone who is reading this, please make Lua your scripting language (if necessary), and then enter this line into the command window:


/print (os.setlocale ("", "all"))


For me, that prints:


English_Australia.1252


If you get something else printed, please post a message pasting the exact thing it says. Don't bother if someone already has, with the same thing in it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zeno   USA  (2,871 posts)  Bio
Date Reply #12 on Mon 11 Jun 2007 02:20 AM (UTC)
Message
I get:
English_United States.1252


(I find it strange that it underscores the first space but not the next)

Zeno McDohl,
Owner of Bleached InuYasha Galaxy
http://www.biyg.org
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #13 on Mon 11 Jun 2007 02:21 AM (UTC)

Amended on Mon 11 Jun 2007 04:12 AM (UTC) by Nick Gammon

Message
The internationalization process, in more detail.

After reading about gettext, and getting some ideas, I have been doing things a bit differently.

The basic steps to internationalization are:


  • Make it possible to display Unicode. This is already partly done if you enable UTF-8 in the output window.

  • Establish the current locale (eg. France, Spain), and - more importantly perhaps - the language that the user wants to use (eg. French, Spanish, Japanese, etc.)

  • At appropriate places in the source code, request translation of strings that are going to be displayed. For example, where formerly it read:

    
      MessageBox ("The proxy server address cannot be blank.");
    


    It now reads:


    
      MessageBox (Translate ("The proxy server address cannot be blank."));
    


    The extra function call to 'Translate' requests that the message "The proxy server address cannot be blank." be converted from English into a message suitable for the user's locale.

    The default behaviour - if you do nothing else - will be to simply return the original message. Thus, the default behaviour is to see the messages in English.

    To simplify this particular operation, which is done quite a lot, a special function call does both - translates and displays a message box (there are over 300 of them):

    
      TMessageBox ("The proxy server address cannot be blank.");
    


  • In order to facilitate the translation, an automated scan of the source code is done, to locate such messages, and write them to a disk file.

    This produces a file which contains stuff like this:

    
    #: doc.cpp:840
    msgid "The proxy server address cannot be blank."
    msgstr ""
    


  • To facilitate the translation of more complex things (like strings with imbedded variables) I have decided to use Lua tables as the translation medium, so this file is now pre-processed into a big Lua table, like this:

    
    messages = {
    
    -- doc.cpp:813
      ["Cannot connect. World name not specified"] =
        "",
    
    -- doc.cpp:840
      ["The proxy server address cannot be blank."] =
        "",
    
    --- and so on ...
      }
    


    Effectively, each unique message is stored in the table, with the original message as the key. Thus a keyed lookup, which is very fast, can find the replacement.

  • This file, which is called the "template" will be distributed with MUSHclient (or made available on the web site). So far it doesn't do a huge amount that is useful, because there are no translations in it yet.

  • People who are interested in localizing - that is, making a translation into a particular language - will make a copy of that file under an appropriate name. For example:


    <MUSHclient executable directory>\locale\DE.lua


    They then edit the copy, and, for each message, devise a translation. Thus the message might now look like this:

    
    messages = {
    
    -- doc.cpp:813
      ["Cannot connect. World name not specified"] =
        "Kann nicht anschließen. Weltname nicht spezifiziert.",
    
    -- doc.cpp:840
      ["The proxy server address cannot be blank."] =
        "Die proxy serveradresse kann nicht leer sein.",
    
    --- and so on ...
      }
    


    There is no tearing rush to convert all messages - you could just do the common ones. Any that are left as an empty string will continue to be shown in English.

  • Once this localized file is updated, the next time MUSHclient is started it will read in the appropriate file, keeping the translations in memory.

  • When it is time to display a message the 'Translate' function will lookup the old message, find the new one (if it exists) and display that instead.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,061 posts)  Bio   Forum Administrator
Date Reply #14 on Mon 11 Jun 2007 02:44 AM (UTC)

Amended on Mon 11 Jun 2007 02:51 AM (UTC) by Nick Gammon

Message
The next interesting problem is messages with imbedded variables. For example, this message:


"The %s contains %i line%s, %i word%s, %i character%s"


The first %s can be either "document" or "selection". The %i items are counts. The other %s items are either the letter "s" for plural, or the empty string, for singular.

A number of problems arise here. For a start, the word order may be different. For example, a translated version might look like this:


There are 4 lines, 5 words, 22 characters in the document.


In this example the "document" word has moved to the back.

Also the pluralization (is that a word?) might be different. The plural of "line" in German is probably not obtained by adding an "s".

To assist in the process of making a correct translation, formatted strings are handled differently, namely by calling a Lua function. Here is how that message might be handled:


formatted = {

-- TextView.cpp:589
  ["The %s contains %i line%s, %i word%s, %i character%s"] =
    function (a, b, c, d, e, f, g)
     
      return ""
    end,  -- function

-- ... and so on ..

}


Formatted messages are in a separate table. This time the item value is an unnamed function that will be called at runtime.

The function is supplied with the arguments that the original one (in the source) had.

Let us take an example:


The selection contains 1 line, 3 words, 20 characters


There are really 7 variables here, and they are automatically named a to g. Their values in this particular case would be:


  1. selection
  2. 1
  3. (empty)
  4. 3
  5. s
  6. 20
  7. s


The translator can now feel free to use those arguments as s/he feels fit. For example, the "s" arguments (items 3, 5 and 7) could be ignored.

The word "selection" could be converted into the equivalent.

The pluralization can be handled by examining the actual numbers and generating appropriate code. The converted function might look like this:


-- TextView.cpp:589
  ["The %s contains %i line%s, %i word%s, %i character%s"] =
    function (a, b, c, d, e, f, g)
       
       local line = "line"
       if b ~= 1 then
         line = "lines"
       end -- plural lines
       
       local word = "word"
       if d ~= 1 then
         word = "words"
       end -- plural words
       
       local character = "character"
       if f ~= 1 then
         character = "characters"
       end -- plural characters
       
      return string.format ("There are %i %s, %i %s, %i %s in the %s",
             b, line, d, word, f, character, a)
             
    end,  -- function


Although this is still English, this illustrates how I have moved the word "document" or "selection" to the end of the message (that is, argument 'a'), and re-evaluted whether to make the word plural by testing the number of each one (arguments 'b', 'd' and 'f').

The nice thing about using Lua, is that things like making numbers plural can be handled by a shared function, which you could put at the start of the translation file, and which can then be used by every function that needs it.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


77,032 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.