Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #27232 > unrolled thread

Multi-language support on embedded plarforms

Started bypozz <pozzugno@gmail.com>
First post2017-09-05 09:30 +0200
Last post2017-09-08 17:33 +0000
Articles 20 on this page of 23 — 14 participants

Back to article view | Back to comp.arch.embedded


Contents

  Multi-language support on embedded plarforms pozz <pozzugno@gmail.com> - 2017-09-05 09:30 +0200
    Re: Multi-language support on embedded plarforms David Brown <david.brown@hesbynett.no> - 2017-09-05 10:43 +0200
      Re: Multi-language support on embedded plarforms Robert Wessel <robertwessel2@yahoo.com> - 2017-09-05 09:56 -0500
        Re: Multi-language support on embedded plarforms Ian Collins <ian-news@hotmail.com> - 2017-09-06 07:50 +1200
          Re: Multi-language support on embedded plarforms Robert Wessel <robertwessel2@yahoo.com> - 2017-09-05 17:11 -0500
            Re: Multi-language support on embedded plarforms Keith Thompson <kst-u@mib.org> - 2017-09-05 15:17 -0700
              Re: Multi-language support on embedded plarforms Robert Wessel <robertwessel2@yahoo.com> - 2017-09-05 19:19 -0500
                Re: Multi-language support on embedded plarforms raltbos@xs4all.nl (Richard Bos) - 2017-09-09 12:37 +0000
                  Re: Multi-language support on embedded plarforms Robert Wessel <robertwessel2@yahoo.com> - 2017-09-09 16:16 -0500
                    Re: Multi-language support on embedded plarforms raltbos@xs4all.nl (Richard Bos) - 2017-09-15 17:17 +0000
            Re: Multi-language support on embedded plarforms Allan Herriman <allanherriman@hotmail.com> - 2017-09-06 11:27 +0000
    Re: Multi-language support on embedded plarforms Paul <paul@pcserviceselectronics.co.uk> - 2017-09-05 10:04 +0100
      Re: Multi-language support on embedded plarforms Theo Markettos <theom+news@chiark.greenend.org.uk> - 2017-09-06 10:55 +0100
    Re: Multi-language support on embedded plarforms Phil Hobbs <pcdhSpamMeSenseless@electrooptical.net> - 2017-09-05 17:00 -0400
    Re: Multi-language support on embedded plarforms Keith Thompson <kst-u@mib.org> - 2017-09-07 10:55 -0700
      Re: Multi-language support on embedded plarforms scott@slp53.sl.home (Scott Lurndal) - 2017-09-07 18:41 +0000
      Re: Multi-language support on embedded plarforms pozz <pozzugno@gmail.com> - 2017-09-08 11:33 +0200
        Re: Multi-language support on embedded plarforms bartc <bc@freeuk.com> - 2017-09-08 11:32 +0100
          Re: Multi-language support on embedded plarforms David Brown <david.brown@hesbynett.no> - 2017-09-08 13:37 +0200
            Re: Multi-language support on embedded plarforms bartc <bc@freeuk.com> - 2017-09-08 14:48 +0100
              Re: Multi-language support on embedded plarforms David Brown <david.brown@hesbynett.no> - 2017-09-08 16:45 +0200
    Re: Multi-language support on embedded plarforms Richard Damon <Richard@Damon-Family.org> - 2017-09-08 10:43 -0400
      Re: Multi-language support on embedded plarforms Mel Wilson <mwilson@the-wire.com> - 2017-09-08 17:33 +0000

Page 1 of 2  [1] 2  Next page →


#27232 — Multi-language support on embedded plarforms

Frompozz <pozzugno@gmail.com>
Date2017-09-05 09:30 +0200
SubjectMulti-language support on embedded plarforms
Message-ID<ooljr9$2kp$1@dont-email.me>
[This message is posted to comp.arch.embedded and comp.lang.c]

Just for reference, an embedded platform based on a MCU with integrated 
Flash, for example a Cortex-Mx device.
Here I consider only western languages (left-to-right and european 
chars, english, french, german, spanish and so on).

The main problem is the translation of strings, maybe 10-100 strings.

I know something about gettext package that can't be used in those 
embeded platforms. However I like the approach of gettext.

   print_to_display(x, y, "Hello world!");

is simply changed in:

   #include <gettext.h>
   ...
   print_to_display(x, y, _("Hello world!"));

In this way, the code stays highly readble as before introducing the 
multi-language support. If a member of a structure needs a string, it is 
a char * as usual.

The solution I found in embedded platforms is to use an array of array 
of strings: one index for the string and one index for the language.

   enum lang_t { ENGLISH, ITALIAN, LANG_N };
   enum string_t { STR_HELLO_WORLD, STR_HOW_ARE_YOU };

   const char *strings[STRING_N][LANG_N] = {
     {  // STR_HELLO_WORLD
       { "Hello world!", "Ciao mondo" }
     },
     {  // STR_HOW_ARE_YOU
       { "How are you?", "Come stai?" }
     },
   };

   static enum lang_t lang = ENGLISH;

   const char *_(int string_idx) {
     return strings[string_idx][lang];
   }

   void set_language(enum lang_t new_language) {
     lang = new_language;
   }


I don't like too much this approach for two reasons.
The first, the line:

   print_to_display(x, y, _(STR_HELLO_WORLD));

is much less readable than

   print_to_display(x, y, _("Hello world!"));


The second, I need to change the type of some members/variables from 
char * to int:

   struct mystruct {
     int title;  // Instead of char *title
     ...
   };


Another approach I'm thinking is to embed all the translations in the 
string, using a separator character that can't be used in normal strings.

   print_to_display(x, y, _("Hello world!|Ciao Mondo!"));

The _() function will search the translated string based on the current 
language. If he can't find, it could return the first translation (english).

This approach has some disadvantages. It's difficult to exclude one 
language from the build. If the languages are more than a couple, the 
strings will be very long. The order of the translations (first english, 
than italian, ...) is important and you have to remember it for every 
string.


What approach do you use?

[toc] | [next] | [standalone]


#27234

FromDavid Brown <david.brown@hesbynett.no>
Date2017-09-05 10:43 +0200
Message-ID<oolo3c$9f9$1@dont-email.me>
In reply to#27232
On 05/09/17 09:30, pozz wrote:
> [This message is posted to comp.arch.embedded and comp.lang.c]
> 
> Just for reference, an embedded platform based on a MCU with integrated
> Flash, for example a Cortex-Mx device.
> Here I consider only western languages (left-to-right and european
> chars, english, french, german, spanish and so on).
> 
> The main problem is the translation of strings, maybe 10-100 strings.
> 
> I know something about gettext package that can't be used in those
> embeded platforms. However I like the approach of gettext.
> 
>   print_to_display(x, y, "Hello world!");
> 
> is simply changed in:
> 
>   #include <gettext.h>
>   ...
>   print_to_display(x, y, _("Hello world!"));
> 
> In this way, the code stays highly readble as before introducing the
> multi-language support. If a member of a structure needs a string, it is
> a char * as usual.
> 
> The solution I found in embedded platforms is to use an array of array
> of strings: one index for the string and one index for the language.
> 
>   enum lang_t { ENGLISH, ITALIAN, LANG_N };
>   enum string_t { STR_HELLO_WORLD, STR_HOW_ARE_YOU };
> 
>   const char *strings[STRING_N][LANG_N] = {
>     {  // STR_HELLO_WORLD
>       { "Hello world!", "Ciao mondo" }
>     },
>     {  // STR_HOW_ARE_YOU
>       { "How are you?", "Come stai?" }
>     },
>   };
> 
>   static enum lang_t lang = ENGLISH;
> 
>   const char *_(int string_idx) {
>     return strings[string_idx][lang];
>   }
> 
>   void set_language(enum lang_t new_language) {
>     lang = new_language;
>   }
> 
> 
> I don't like too much this approach for two reasons.
> The first, the line:
> 
>   print_to_display(x, y, _(STR_HELLO_WORLD));
> 
> is much less readable than
> 
>   print_to_display(x, y, _("Hello world!"));
> 
> 
> The second, I need to change the type of some members/variables from
> char * to int:
> 
>   struct mystruct {
>     int title;  // Instead of char *title
>     ...
>   };
> 
> 
> Another approach I'm thinking is to embed all the translations in the
> string, using a separator character that can't be used in normal strings.
> 
>   print_to_display(x, y, _("Hello world!|Ciao Mondo!"));
> 
> The _() function will search the translated string based on the current
> language. If he can't find, it could return the first translation
> (english).
> 
> This approach has some disadvantages. It's difficult to exclude one
> language from the build. If the languages are more than a couple, the
> strings will be very long. The order of the translations (first english,
> than italian, ...) is important and you have to remember it for every
> string.
> 
> 
> What approach do you use?

I think if you are looking for a pure C approach, and you want to keep
it efficient, then using the enumerated type as an index is the best choice.

But rather than writing all the strings directly in C, I would keep
track of them in a spreadsheet saved in tab delimited format, and use a
little script to turn it into a C header file declaring the enum, and a
C source file initialising the array.  It just makes it easier to keep
track of everything, and saves a great deal of effort when you need to
get someone else to make the translation strings.


[toc] | [prev] | [next] | [standalone]


#27237

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-09-05 09:56 -0500
Message-ID<83etqc173gvifoa9hpp1ucrnuf481b91tg@4ax.com>
In reply to#27234
On Tue, 05 Sep 2017 10:43:24 +0200, David Brown
<david.brown@hesbynett.no> wrote:

>On 05/09/17 09:30, pozz wrote:
>> [This message is posted to comp.arch.embedded and comp.lang.c]
>> 
>> Just for reference, an embedded platform based on a MCU with integrated
>> Flash, for example a Cortex-Mx device.
>> Here I consider only western languages (left-to-right and european
>> chars, english, french, german, spanish and so on).
>> 
>> The main problem is the translation of strings, maybe 10-100 strings.
>> 
>> I know something about gettext package that can't be used in those
>> embeded platforms. However I like the approach of gettext.
>> 
>>   print_to_display(x, y, "Hello world!");
>> 
>> is simply changed in:
>> 
>>   #include <gettext.h>
>>   ...
>>   print_to_display(x, y, _("Hello world!"));
>> 
>> In this way, the code stays highly readble as before introducing the
>> multi-language support. If a member of a structure needs a string, it is
>> a char * as usual.
>> 
>> The solution I found in embedded platforms is to use an array of array
>> of strings: one index for the string and one index for the language.
>> 
>>   enum lang_t { ENGLISH, ITALIAN, LANG_N };
>>   enum string_t { STR_HELLO_WORLD, STR_HOW_ARE_YOU };
>> 
>>   const char *strings[STRING_N][LANG_N] = {
>>     {  // STR_HELLO_WORLD
>>       { "Hello world!", "Ciao mondo" }
>>     },
>>     {  // STR_HOW_ARE_YOU
>>       { "How are you?", "Come stai?" }
>>     },
>>   };
>> 
>>   static enum lang_t lang = ENGLISH;
>> 
>>   const char *_(int string_idx) {
>>     return strings[string_idx][lang];
>>   }
>> 
>>   void set_language(enum lang_t new_language) {
>>     lang = new_language;
>>   }
>> 
>> 
>> I don't like too much this approach for two reasons.
>> The first, the line:
>> 
>>   print_to_display(x, y, _(STR_HELLO_WORLD));
>> 
>> is much less readable than
>> 
>>   print_to_display(x, y, _("Hello world!"));
>> 
>> 
>> The second, I need to change the type of some members/variables from
>> char * to int:
>> 
>>   struct mystruct {
>>     int title;  // Instead of char *title
>>     ...
>>   };
>> 
>> 
>> Another approach I'm thinking is to embed all the translations in the
>> string, using a separator character that can't be used in normal strings.
>> 
>>   print_to_display(x, y, _("Hello world!|Ciao Mondo!"));
>> 
>> The _() function will search the translated string based on the current
>> language. If he can't find, it could return the first translation
>> (english).
>> 
>> This approach has some disadvantages. It's difficult to exclude one
>> language from the build. If the languages are more than a couple, the
>> strings will be very long. The order of the translations (first english,
>> than italian, ...) is important and you have to remember it for every
>> string.
>> 
>> 
>> What approach do you use?
>
>I think if you are looking for a pure C approach, and you want to keep
>it efficient, then using the enumerated type as an index is the best choice.
>
>But rather than writing all the strings directly in C, I would keep
>track of them in a spreadsheet saved in tab delimited format, and use a
>little script to turn it into a C header file declaring the enum, and a
>C source file initialising the array.  It just makes it easier to keep
>track of everything, and saves a great deal of effort when you need to
>get someone else to make the translation strings.


We use a preprocessor approach as well, although not from a
spreadsheet.  An advantage of a preprocessor, is that it makes it easy
to slot default messages (IOW English) in for items which have missing
translations, and to build subsets of the supported languages and
messages to keep space requirements down.

Paul mentioned the difficulty of keeping the different translations in
sync; the preprocessor can help there too, if you put a version code
(a timestamp, in our case) on each version of each message.  Then the
preprocessor can warn if the English message was updated without the
timestamp being updated (hopefully after being reviewed!) on the
Italian message.

[toc] | [prev] | [next] | [standalone]


#27242

FromIan Collins <ian-news@hotmail.com>
Date2017-09-06 07:50 +1200
Message-ID<f18dgsFgq3rU1@mid.individual.net>
In reply to#27237
On 09/ 6/17 02:56 AM, Robert Wessel wrote:
> On Tue, 05 Sep 2017 10:43:24 +0200, David Brown
> <david.brown@hesbynett.no> wrote:

>> I think if you are looking for a pure C approach, and you want to keep
>> it efficient, then using the enumerated type as an index is the best choice.
>>
>> But rather than writing all the strings directly in C, I would keep
>> track of them in a spreadsheet saved in tab delimited format, and use a
>> little script to turn it into a C header file declaring the enum, and a
>> C source file initialising the array.  It just makes it easier to keep
>> track of everything, and saves a great deal of effort when you need to
>> get someone else to make the translation strings.
>
>
> We use a preprocessor approach as well, although not from a
> spreadsheet.  An advantage of a preprocessor, is that it makes it easy
> to slot default messages (IOW English) in for items which have missing
> translations, and to build subsets of the supported languages and
> messages to keep space requirements down.
>
> Paul mentioned the difficulty of keeping the different translations in
> sync; the preprocessor can help there too, if you put a version code
> (a timestamp, in our case) on each version of each message.  Then the
> preprocessor can warn if the English message was updated without the
> timestamp being updated (hopefully after being reviewed!) on the
> Italian message.

If you store your spreadsheet in plain text (SCV), your version control 
system can keep track of changes for you!

-- 
Ian

[toc] | [prev] | [next] | [standalone]


#27243

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-09-05 17:11 -0500
Message-ID<8v7uqc57sf3glk5fpuat1cs5srt23r5b76@4ax.com>
In reply to#27242
On Wed, 6 Sep 2017 07:50:52 +1200, Ian Collins <ian-news@hotmail.com>
wrote:

>On 09/ 6/17 02:56 AM, Robert Wessel wrote:
>> On Tue, 05 Sep 2017 10:43:24 +0200, David Brown
>> <david.brown@hesbynett.no> wrote:
>
>>> I think if you are looking for a pure C approach, and you want to keep
>>> it efficient, then using the enumerated type as an index is the best choice.
>>>
>>> But rather than writing all the strings directly in C, I would keep
>>> track of them in a spreadsheet saved in tab delimited format, and use a
>>> little script to turn it into a C header file declaring the enum, and a
>>> C source file initialising the array.  It just makes it easier to keep
>>> track of everything, and saves a great deal of effort when you need to
>>> get someone else to make the translation strings.
>>
>>
>> We use a preprocessor approach as well, although not from a
>> spreadsheet.  An advantage of a preprocessor, is that it makes it easy
>> to slot default messages (IOW English) in for items which have missing
>> translations, and to build subsets of the supported languages and
>> messages to keep space requirements down.
>>
>> Paul mentioned the difficulty of keeping the different translations in
>> sync; the preprocessor can help there too, if you put a version code
>> (a timestamp, in our case) on each version of each message.  Then the
>> preprocessor can warn if the English message was updated without the
>> timestamp being updated (hopefully after being reviewed!) on the
>> Italian message.
>
>If you store your spreadsheet in plain text (SCV), your version control 
>system can keep track of changes for you!


Well yes, (and ours are text based), but I've yet to see a SCM that
can tell you that someone updated the English version of message#14,
but hasn't validated or updated the Italian one yet.  You can
certainly get a diff and manually see where changes have been made,
but that still leaves you with a manual comparison to the
translations, and no way of tracking that the validations have been
done.

[toc] | [prev] | [next] | [standalone]


#27244

FromKeith Thompson <kst-u@mib.org>
Date2017-09-05 15:17 -0700
Message-ID<lnvakw94dn.fsf@kst-u.example.com>
In reply to#27243
Robert Wessel <robertwessel2@yahoo.com> writes:
> On Wed, 6 Sep 2017 07:50:52 +1200, Ian Collins <ian-news@hotmail.com>
> wrote:
>>On 09/ 6/17 02:56 AM, Robert Wessel wrote:
[...]
>>> Paul mentioned the difficulty of keeping the different translations in
>>> sync; the preprocessor can help there too, if you put a version code
>>> (a timestamp, in our case) on each version of each message.  Then the
>>> preprocessor can warn if the English message was updated without the
>>> timestamp being updated (hopefully after being reviewed!) on the
>>> Italian message.
>>
>>If you store your spreadsheet in plain text (SCV), your version control 
>>system can keep track of changes for you!
>
>
> Well yes, (and ours are text based), but I've yet to see a SCM that
> can tell you that someone updated the English version of message#14,
> but hasn't validated or updated the Italian one yet.  You can
> certainly get a diff and manually see where changes have been made,
> but that still leaves you with a manual comparison to the
> translations, and no way of tracking that the validations have been
> done.

The "git blame" command tells you, for each line in a file, when that
line was most recently modified.  Other SCMs have similar tools.
I imagine you could build some tools on top of that that could
warn you, for example, that the English version of message #14 was
updated yesterday but the Italian version hasn't been changed in
the last year.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#27248

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-09-05 19:19 -0500
Message-ID<v0fuqcpucs47vl7eqkbumnn8jle8aadvk9@4ax.com>
In reply to#27244
On Tue, 05 Sep 2017 15:17:56 -0700, Keith Thompson <kst-u@mib.org>
wrote:

>Robert Wessel <robertwessel2@yahoo.com> writes:
>> On Wed, 6 Sep 2017 07:50:52 +1200, Ian Collins <ian-news@hotmail.com>
>> wrote:
>>>On 09/ 6/17 02:56 AM, Robert Wessel wrote:
>[...]
>>>> Paul mentioned the difficulty of keeping the different translations in
>>>> sync; the preprocessor can help there too, if you put a version code
>>>> (a timestamp, in our case) on each version of each message.  Then the
>>>> preprocessor can warn if the English message was updated without the
>>>> timestamp being updated (hopefully after being reviewed!) on the
>>>> Italian message.
>>>
>>>If you store your spreadsheet in plain text (SCV), your version control 
>>>system can keep track of changes for you!
>>
>>
>> Well yes, (and ours are text based), but I've yet to see a SCM that
>> can tell you that someone updated the English version of message#14,
>> but hasn't validated or updated the Italian one yet.  You can
>> certainly get a diff and manually see where changes have been made,
>> but that still leaves you with a manual comparison to the
>> translations, and no way of tracking that the validations have been
>> done.
>
>The "git blame" command tells you, for each line in a file, when that
>line was most recently modified.  Other SCMs have similar tools.
>I imagine you could build some tools on top of that that could
>warn you, for example, that the English version of message #14 was
>updated yesterday but the Italian version hasn't been changed in
>the last year.


A problem is when a change needs to be made to only some translations
of a message.  Let's say the English one was awkwardly worded, and
thus modified, but (some of) the other translations don't need to be
changed (although they should probably be reviewed).  You need a way
to track when a particular translation was last validated against the
intended meaning of the message (OK, let's be blunt, the base English
message), and against which version it was validated.  So we have:

{
msg=FILENOTFOUND,v=3
EN="File not found",m=05-09-2017,v=3
IT="File non trovato",m=01-01-2015,v=3
}

[toc] | [prev] | [next] | [standalone]


#27287

Fromraltbos@xs4all.nl (Richard Bos)
Date2017-09-09 12:37 +0000
Message-ID<59b3e042.2829906@news.xs4all.nl>
In reply to#27248
Robert Wessel <robertwessel2@yahoo.com> wrote:

> On Tue, 05 Sep 2017 15:17:56 -0700, Keith Thompson <kst-u@mib.org>
> 
> >Robert Wessel <robertwessel2@yahoo.com> writes:

> >> Well yes, (and ours are text based), but I've yet to see a SCM that
> >> can tell you that someone updated the English version of message#14,
> >> but hasn't validated or updated the Italian one yet.  You can
> >> certainly get a diff and manually see where changes have been made,
> >> but that still leaves you with a manual comparison to the
> >> translations, and no way of tracking that the validations have been
> >> done.
> >
> >The "git blame" command tells you, for each line in a file, when that
> >line was most recently modified.  Other SCMs have similar tools.
> >I imagine you could build some tools on top of that that could
> >warn you, for example, that the English version of message #14 was
> >updated yesterday but the Italian version hasn't been changed in
> >the last year.
> 
> A problem is when a change needs to be made to only some translations
> of a message.  Let's say the English one was awkwardly worded, and
> thus modified, but (some of) the other translations don't need to be
> changed (although they should probably be reviewed).

I'd like to point out that none of that is a technical problem. It's a
management (and sometimes political) problem, and therefore needs a
solution at a management level, not primarily a technical one. There may
be technical _aids_ to the managerial solution, but not a technical
solution /per se/.

Richard

[toc] | [prev] | [next] | [standalone]


#27289

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-09-09 16:16 -0500
Message-ID<1gm8rct19j9fni0muuv7e9knjg6tdnjp92@4ax.com>
In reply to#27287
On Sat, 09 Sep 2017 12:37:46 GMT, raltbos@xs4all.nl (Richard Bos)
wrote:

>Robert Wessel <robertwessel2@yahoo.com> wrote:
>
>> On Tue, 05 Sep 2017 15:17:56 -0700, Keith Thompson <kst-u@mib.org>
>> 
>> >Robert Wessel <robertwessel2@yahoo.com> writes:
>
>> >> Well yes, (and ours are text based), but I've yet to see a SCM that
>> >> can tell you that someone updated the English version of message#14,
>> >> but hasn't validated or updated the Italian one yet.  You can
>> >> certainly get a diff and manually see where changes have been made,
>> >> but that still leaves you with a manual comparison to the
>> >> translations, and no way of tracking that the validations have been
>> >> done.
>> >
>> >The "git blame" command tells you, for each line in a file, when that
>> >line was most recently modified.  Other SCMs have similar tools.
>> >I imagine you could build some tools on top of that that could
>> >warn you, for example, that the English version of message #14 was
>> >updated yesterday but the Italian version hasn't been changed in
>> >the last year.
>> 
>> A problem is when a change needs to be made to only some translations
>> of a message.  Let's say the English one was awkwardly worded, and
>> thus modified, but (some of) the other translations don't need to be
>> changed (although they should probably be reviewed).
>
>I'd like to point out that none of that is a technical problem. It's a
>management (and sometimes political) problem, and therefore needs a
>solution at a management level, not primarily a technical one. There may
>be technical _aids_ to the managerial solution, but not a technical
>solution /per se/.


Sure, but you can say the same about source code and configuration
management too.

[toc] | [prev] | [next] | [standalone]


#27301

Fromraltbos@xs4all.nl (Richard Bos)
Date2017-09-15 17:17 +0000
Message-ID<59bc0a14.2751390@news.xs4all.nl>
In reply to#27289
Robert Wessel <robertwessel2@yahoo.com> wrote:

> On Sat, 09 Sep 2017 12:37:46 GMT, raltbos@xs4all.nl (Richard Bos)
> >Robert Wessel <robertwessel2@yahoo.com> wrote:
> >
> >> A problem is when a change needs to be made to only some translations
> >> of a message.  Let's say the English one was awkwardly worded, and
> >> thus modified, but (some of) the other translations don't need to be
> >> changed (although they should probably be reviewed).
> >
> >I'd like to point out that none of that is a technical problem. It's a
> >management (and sometimes political) problem, and therefore needs a
> >solution at a management level, not primarily a technical one. There may
> >be technical _aids_ to the managerial solution, but not a technical
> >solution /per se/.
> 
> Sure, but you can say the same about source code and configuration
> management too.

Yes, and I do. If you can't do a desk check, but require a colour-coding
IDE to read your code, you're not a programmer, you're a hack. Liking
syntax colouring is fine, it's needing it which is the problem: the IDE
should aid your code comprehension, not create it.

Similarly, if you can't work with two people on one problem without
needing to go through Github, you don't have enough social skills to be
a team player. Two thousand is another matter, but there, too, the basic
problem is organising the teams, _not_ setting up the Git repository.


Richard

[toc] | [prev] | [next] | [standalone]


#27267

FromAllan Herriman <allanherriman@hotmail.com>
Date2017-09-06 11:27 +0000
Message-ID<59afdb9a$0$16747$b1db1813$d948b532@news.astraweb.com>
In reply to#27243
On Tue, 05 Sep 2017 17:11:40 -0500, Robert Wessel wrote:

> On Wed, 6 Sep 2017 07:50:52 +1200, Ian Collins <ian-news@hotmail.com>
> wrote:
> 
>>On 09/ 6/17 02:56 AM, Robert Wessel wrote:
>>> On Tue, 05 Sep 2017 10:43:24 +0200, David Brown
>>> <david.brown@hesbynett.no> wrote:
>>
>>>> I think if you are looking for a pure C approach, and you want to
>>>> keep it efficient, then using the enumerated type as an index is the
>>>> best choice.
>>>>
>>>> But rather than writing all the strings directly in C, I would keep
>>>> track of them in a spreadsheet saved in tab delimited format, and use
>>>> a little script to turn it into a C header file declaring the enum,
>>>> and a C source file initialising the array.  It just makes it easier
>>>> to keep track of everything, and saves a great deal of effort when
>>>> you need to get someone else to make the translation strings.
>>>
>>>
>>> We use a preprocessor approach as well, although not from a
>>> spreadsheet.  An advantage of a preprocessor, is that it makes it easy
>>> to slot default messages (IOW English) in for items which have missing
>>> translations, and to build subsets of the supported languages and
>>> messages to keep space requirements down.
>>>
>>> Paul mentioned the difficulty of keeping the different translations in
>>> sync; the preprocessor can help there too, if you put a version code
>>> (a timestamp, in our case) on each version of each message.  Then the
>>> preprocessor can warn if the English message was updated without the
>>> timestamp being updated (hopefully after being reviewed!) on the
>>> Italian message.
>>
>>If you store your spreadsheet in plain text (SCV), your version control
>>system can keep track of changes for you!
> 
> 
> Well yes, (and ours are text based), but I've yet to see a SCM that can
> tell you that someone updated the English version of message#14, but
> hasn't validated or updated the Italian one yet.  You can certainly get
> a diff and manually see where changes have been made, but that still
> leaves you with a manual comparison to the translations, and no way of
> tracking that the validations have been done.


Some SCM tools allow the use of "hook scripts" - bits of code or programs 
that you can hook into various SCM actions or states.  You would need to 
write the scripts yourself, but it ought to be possible to disallow a 
checkin on the English file if the other language files haven't been 
updated.

I did a similar thing with Tortoise SVN once: for some reason we had 
document source (e.g. Word) and PDF output both in the SCM system, and a 
hook script would check if one was being checked in without the other, 
and abort the checkin with a suitable message if one was missing.

Regards,
Allan

[toc] | [prev] | [next] | [standalone]


#27235

FromPaul <paul@pcserviceselectronics.co.uk>
Date2017-09-05 10:04 +0100
Message-ID<MPG.341878f77f47090298982e@172.16.0.1>
In reply to#27232
In article <ooljr9$2kp$1@dont-email.me>, pozzugno@gmail.com says...
> 
> [This message is posted to comp.arch.embedded and comp.lang.c]
> 
> Just for reference, an embedded platform based on a MCU with integrated 
> Flash, for example a Cortex-Mx device.
> Here I consider only western languages (left-to-right and european 
> chars, english, french, german, spanish and so on).

Whatever method you choose there is one thing thta has to be done
procedurally and will get overlooked if a time constrained bug fix 
occurs. That is that part of the fix is to change a string to correct
an error, change the feature, whoever is updataing it,'forgets' or
is time pressured for release and fails to to do ALL the other 
translations.

There is no easy solution for that as that involves people.
 
> The main problem is the translation of strings, maybe 10-100 strings.
> 
> I know something about gettext package that can't be used in those 
> embeded platforms. However I like the approach of gettext.
> 
>    print_to_display(x, y, "Hello world!");
> 
> is simply changed in:
> 
>    #include <gettext.h>
>    ...
>    print_to_display(x, y, _("Hello world!"));
> 
> In this way, the code stays highly readble as before introducing the 
> multi-language support. If a member of a structure needs a string, it is 
> a char * as usual.
> 
> The solution I found in embedded platforms is to use an array of array 
> of strings: one index for the string and one index for the language.
> 
>    enum lang_t { ENGLISH, ITALIAN, LANG_N };
>    enum string_t { STR_HELLO_WORLD, STR_HOW_ARE_YOU };
> 
>    const char *strings[STRING_N][LANG_N] = {
>      {  // STR_HELLO_WORLD
>        { "Hello world!", "Ciao mondo" }
>      },
>      {  // STR_HOW_ARE_YOU
>        { "How are you?", "Come stai?" }
>      },
>    };

The problem with having situations where the SAME string is in two 
places, I have seen fail on desktop applications.

If the string in the translation tables is NOT identical to string
in the code section, it fails.

e.g.	Table contains	"hello world"

	Code contains		"hello world\n"

This also is more likely to happen where the same string has been
copy/pasted as two different parts of code to actually print the
same string. Then a correction is required, so someone diligently
corrects the translation table and ONE place in the code where they
see the problem, but does not realise there are OTHER instances of
the same string.


Whilst having index keys to strings (as Constants) may be less readable
and could always have inline comments, it does save on storage space
and iterative long string compares, if excecution speed is also a 
problem. Also cuts down on typos and other accidental differences 
between strings.

Whatever you do need procedures to ensure all strings are translated 
to all languages, for every change of any string. The human part is the
weak link.

.... 
> What approach do you use?



-- 
Paul Carpenter          | paul@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/>    PC Services
<http://www.pcserviceselectronics.co.uk/LogicCell/> Logic Gate Education
<http://www.pcserviceselectronics.co.uk/fonts/>     Timing Diagram Font
<http://www.badweb.org.uk/>    For those web sites you hate

[toc] | [prev] | [next] | [standalone]


#27266

FromTheo Markettos <theom+news@chiark.greenend.org.uk>
Date2017-09-06 10:55 +0100
Message-ID<p1r*lg-Aw@news.chiark.greenend.org.uk>
In reply to#27235
In comp.arch.embedded Paul <paul@pcserviceselectronics.co.uk> wrote:
> Whilst having index keys to strings (as Constants) may be less readable
> and could always have inline comments, it does save on storage space
> and iterative long string compares, if excecution speed is also a 
> problem. Also cuts down on typos and other accidental differences 
> between strings.

I wonder if you could do something using the strings themselves as
identifiers.

In other words _("Hello world") is a function called _() passed a
const char *

The first thing the _() function does is look up that char * in a hash table
to see if it's something we've seen before.  If so, it returns a pointer to
the translated string.

If not, it matches the string against a list of translations and inserts the
pointer to the translation into the hash table.

The tradeoff is that it's more work at runtime.  But essentially we only
have to walk the string once per run, and then all we have to do is hash the
pointer each time we use it.  That's not zero overhead, but probably much
less work than printf() is already doing (if you're using that).
It's a bit more problematic if first-time walking the string might be too
costly on some code paths.

> Whatever you do need procedures to ensure all strings are translated 
> to all languages, for every change of any string. The human part is the
> weak link.

gettext or another compiler technique could be used to scrape out the
strings to build the translation table.  You might be able to instrument
that to raise an error at compile time when the extracted translations don't
match the translations in the database.

Theo

[toc] | [prev] | [next] | [standalone]


#27250

FromPhil Hobbs <pcdhSpamMeSenseless@electrooptical.net>
Date2017-09-05 17:00 -0400
Message-ID<oongli$54c$2@dont-email.me>
In reply to#27232
On 09/05/2017 03:30 AM, pozz wrote:
> [This message is posted to comp.arch.embedded and comp.lang.c]
> 
> Just for reference, an embedded platform based on a MCU with integrated 
> Flash, for example a Cortex-Mx device.
> Here I consider only western languages (left-to-right and european 
> chars, english, french, german, spanish and so on).
> 
> The main problem is the translation of strings, maybe 10-100 strings.
> 
> I know something about gettext package that can't be used in those 
> embeded platforms. However I like the approach of gettext.
> 
>    print_to_display(x, y, "Hello world!");
> 
> is simply changed in:
> 
>    #include <gettext.h>
>    ...
>    print_to_display(x, y, _("Hello world!"));
> 
> In this way, the code stays highly readble as before introducing the 
> multi-language support. If a member of a structure needs a string, it is 
> a char * as usual.
> 
> The solution I found in embedded platforms is to use an array of array 
> of strings: one index for the string and one index for the language.
> 
>    enum lang_t { ENGLISH, ITALIAN, LANG_N };
>    enum string_t { STR_HELLO_WORLD, STR_HOW_ARE_YOU };
> 
>    const char *strings[STRING_N][LANG_N] = {
>      {  // STR_HELLO_WORLD
>        { "Hello world!", "Ciao mondo" }
>      },
>      {  // STR_HOW_ARE_YOU
>        { "How are you?", "Come stai?" }
>      },
>    };
> 
>    static enum lang_t lang = ENGLISH;
> 
>    const char *_(int string_idx) {
>      return strings[string_idx][lang];
>    }
> 
>    void set_language(enum lang_t new_language) {
>      lang = new_language;
>    }
> 
> 
> I don't like too much this approach for two reasons.
> The first, the line:
> 
>    print_to_display(x, y, _(STR_HELLO_WORLD));
> 
> is much less readable than
> 
>    print_to_display(x, y, _("Hello world!"));
> 
> 
> The second, I need to change the type of some members/variables from 
> char * to int:
> 
>    struct mystruct {
>      int title;  // Instead of char *title
>      ...
>    };
> 
> 
> Another approach I'm thinking is to embed all the translations in the 
> string, using a separator character that can't be used in normal strings.
> 
>    print_to_display(x, y, _("Hello world!|Ciao Mondo!"));
> 
> The _() function will search the translated string based on the current 
> language. If he can't find, it could return the first translation 
> (english).
> 
> This approach has some disadvantages. It's difficult to exclude one 
> language from the build. If the languages are more than a couple, the 
> strings will be very long. The order of the translations (first english, 
> than italian, ...) is important and you have to remember it for every 
> string.
> 
> 
> What approach do you use?

Stick to plain ASCII and expect the users to adjust. ;)

Cheers

Phil Hobbs

(Who doesn't build a lot of things that sell in the millions.)

-- 
Dr Philip C D Hobbs
Principal Consultant
ElectroOptical Innovations LLC
Optics, Electro-optics, Photonics, Analog Electronics

160 North State Road #203
Briarcliff Manor NY 10510

hobbs at electrooptical dot net
http://electrooptical.net

[toc] | [prev] | [next] | [standalone]


#27268

FromKeith Thompson <kst-u@mib.org>
Date2017-09-07 10:55 -0700
Message-ID<871snil7g3.fsf@kst-u.example.com>
In reply to#27232
pozz <pozzugno@gmail.com> writes:
> [This message is posted to comp.arch.embedded and comp.lang.c]
>
> Just for reference, an embedded platform based on a MCU with
> integrated Flash, for example a Cortex-Mx device.
> Here I consider only western languages (left-to-right and european
> chars, english, french, german, spanish and so on).
>
> The main problem is the translation of strings, maybe 10-100 strings.
>
> I know something about gettext package that can't be used in those
> embeded platforms. However I like the approach of gettext.
>
>   print_to_display(x, y, "Hello world!");
>
> is simply changed in:
>
>   #include <gettext.h>
>   ...
>   print_to_display(x, y, _("Hello world!"));
[snip]

GNU gettext is free software, licensed under GPLv3.  I wonder if you
could grab a copy of it, remove any functionality you don't need, and
end up with something small enough to work on your embedded system.

In a very quick look at the gettext sources, I see that the
gettext-runtime/src subdirectory contains about 1300 lines of C code.
If that's all that needs to run on the target system, you might even be
able to use it without modification.

(Any licensing issues are left as an exercise.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#27269

Fromscott@slp53.sl.home (Scott Lurndal)
Date2017-09-07 18:41 +0000
Message-ID<QpgsB.97872$8I2.55349@fx40.iad>
In reply to#27268
Keith Thompson <kst-u@mib.org> writes:
>pozz <pozzugno@gmail.com> writes:
>> [This message is posted to comp.arch.embedded and comp.lang.c]
>>
>> Just for reference, an embedded platform based on a MCU with
>> integrated Flash, for example a Cortex-Mx device.
>> Here I consider only western languages (left-to-right and european
>> chars, english, french, german, spanish and so on).
>>
>> The main problem is the translation of strings, maybe 10-100 strings.
>>
>> I know something about gettext package that can't be used in those
>> embeded platforms. However I like the approach of gettext.
>>
>>   print_to_display(x, y, "Hello world!");
>>
>> is simply changed in:
>>
>>   #include <gettext.h>
>>   ...
>>   print_to_display(x, y, _("Hello world!"));
>[snip]
>
>GNU gettext is free software, licensed under GPLv3.  I wonder if you
>could grab a copy of it, remove any functionality you don't need, and
>end up with something small enough to work on your embedded system.
>
>In a very quick look at the gettext sources, I see that the
>gettext-runtime/src subdirectory contains about 1300 lines of C code.
>If that's all that needs to run on the target system, you might even be
>able to use it without modification.
>
>(Any licensing issues are left as an exercise.)

GPLv3 would likely preclude use of gettext in
proprietary embedded code.

There is equivalent functionality in the *BSD variants
that are licensed much more liberally.

[toc] | [prev] | [next] | [standalone]


#27273

Frompozz <pozzugno@gmail.com>
Date2017-09-08 11:33 +0200
Message-ID<ooto66$6ff$1@dont-email.me>
In reply to#27268
Il 07/09/2017 19:55, Keith Thompson ha scritto:
> pozz <pozzugno@gmail.com> writes:
>> [This message is posted to comp.arch.embedded and comp.lang.c]
>>
>> Just for reference, an embedded platform based on a MCU with
>> integrated Flash, for example a Cortex-Mx device.
>> Here I consider only western languages (left-to-right and european
>> chars, english, french, german, spanish and so on).
>>
>> The main problem is the translation of strings, maybe 10-100 strings.
>>
>> I know something about gettext package that can't be used in those
>> embeded platforms. However I like the approach of gettext.
>>
>>    print_to_display(x, y, "Hello world!");
>>
>> is simply changed in:
>>
>>    #include <gettext.h>
>>    ...
>>    print_to_display(x, y, _("Hello world!"));
> [snip]
> 
> GNU gettext is free software, licensed under GPLv3.  I wonder if you
> could grab a copy of it, remove any functionality you don't need, and
> end up with something small enough to work on your embedded system.
> 
> In a very quick look at the gettext sources, I see that the
> gettext-runtime/src subdirectory contains about 1300 lines of C code.
> If that's all that needs to run on the target system, you might even be
> able to use it without modification.

This is a good suggestion. I'm not an expert of gettext, however I 
remember it loads/search for right strings (based on current language) 
at runtime, looking at the content of a binary file (mo extension).

In my embedded platform I don't have a real filesystem so I can't access 
"files" at runtime.

Maybe I could add the mo files in the output binary file (the image of 
the Flash memory of the MCU) at exact locations and change gettext code 
to look at those fixed addresses instead of accessing files.

Anyway thanks for the suggestions.


> (Any licensing issues are left as an exercise.)

And this is another good point to study.

[toc] | [prev] | [next] | [standalone]


#27275

Frombartc <bc@freeuk.com>
Date2017-09-08 11:32 +0100
Message-ID<IkusB.792292$Bj2.352282@fx24.am4>
In reply to#27273
On 08/09/2017 10:33, pozz wrote:
> Il 07/09/2017 19:55, Keith Thompson ha scritto:

>> In a very quick look at the gettext sources, I see that the
>> gettext-runtime/src subdirectory contains about 1300 lines of C code.
>> If that's all that needs to run on the target system, you might even be
>> able to use it without modification.
> 
> This is a good suggestion. I'm not an expert of gettext, however I 
> remember it loads/search for right strings (based on current language) 
> at runtime, looking at the content of a binary file (mo extension).
> 
> In my embedded platform I don't have a real filesystem so I can't access 
> "files" at runtime.
> 
> Maybe I could add the mo files in the output binary file (the image of 
> the Flash memory of the MCU) at exact locations and change gettext code 
> to look at those fixed addresses instead of accessing files.
> 
> Anyway thanks for the suggestions.

gettext looks like a very heavy-duty approach. (A lot of these third 
party solutions are. My experience was that a third party library that 
took care of 5% of the functionality of my application, would be several 
times bigger than my entire app.)

The method is basically this, assuming you have tables of messages for 
all languages in memory:

* Take an English message M
* Look it up in the English table, to get index N (with 100 messages,
   a linear search will do)
* If N is in range, return the string from table[N] for language L
* If M wasn't found, just return M, the English version.

So, probably a 10 or 20 line function.

This would require two copies of each English message, one in the 
source, and one in a searchable table. And that needs maintenance.

You might be able to get around that by embedding a serial number in 
each English message:

    puts(_("Please enter filename: !078"));

Here the '!078" is the number and does not appear (or you can use {78} 
etc, any scheme will do).

Now you just have to search the table for language L for a message with 
the same number. (You don't need to convert to an integer, just compare 
the last few characters.)

Of course, you need to return a string without the !078 etc in it. For 
that purpose, it might be better to put this number at the start. Then 
you return a string pointing to the just past the number.

(See example below using such a scheme. This might give some ideas.)

You can use the number as an actual index, but the maintenance becomes 
harder.

There is still the problem of producing a list of English messages for 
translators to work from. But the format and ordering of that is not 
critical.

>> (Any licensing issues are left as an exercise.)
> 
> And this is another good point to study.

Another reason to forget using anyone else's library.

--------------------------------------------------------------

#include <stdio.h>
#include <string.h>

char *italian[] = {
     "1!uno",
     "2!due",
     "3!tre",
     "4!quattro",
     "5!fine",
};
char *spanish[] = {
     "2!dos",
     "3!tres",
     "1!uno",
     "4!cuatro",
     "5!fin"
};
char *german[] = {
     "4!vier",         // ordering doesn't matter
     "5!Ende",
     "1!eins",
     "2!zwei",
     "3!drei"
};

//char **currlang = italian;
//char **currlang = german;
char **currlang = spanish;
//char **currlang = NULL;

int nmessages=sizeof(italian)/sizeof(italian[0]);

char* skipprefix(char* M){
     char *s=M;
     while (*s!='!' && *s!=0) ++s;
     if (*s==0) return M;
     return s+1;
}

char* lookup(char* M){
     char *s;
     int i,len;

     s=skipprefix(M);
     len=s-M;
     if (currlang==NULL || len==0) return s;     // English

     for (i=0; i<nmessages; ++i)
         if (memcmp(currlang[i],M,len)==0)
             return skipprefix(currlang[i]);
     return s;                                   // not found
}


int main(void) {
     int i;

     puts(lookup("1!one"));
     puts(lookup("2!two"));
     puts(lookup("3!three"));
     puts(lookup("5!end"));
}


-- 
bartc


[toc] | [prev] | [next] | [standalone]


#27278

FromDavid Brown <david.brown@hesbynett.no>
Date2017-09-08 13:37 +0200
Message-ID<ootvem$gpm$1@dont-email.me>
In reply to#27275
On 08/09/17 12:32, bartc wrote:
> On 08/09/2017 10:33, pozz wrote:
>> Il 07/09/2017 19:55, Keith Thompson ha scritto:
> 
>>> In a very quick look at the gettext sources, I see that the
>>> gettext-runtime/src subdirectory contains about 1300 lines of C code.
>>> If that's all that needs to run on the target system, you might even be
>>> able to use it without modification.
>>
>> This is a good suggestion. I'm not an expert of gettext, however I
>> remember it loads/search for right strings (based on current language)
>> at runtime, looking at the content of a binary file (mo extension).
>>
>> In my embedded platform I don't have a real filesystem so I can't
>> access "files" at runtime.
>>
>> Maybe I could add the mo files in the output binary file (the image of
>> the Flash memory of the MCU) at exact locations and change gettext
>> code to look at those fixed addresses instead of accessing files.
>>
>> Anyway thanks for the suggestions.
> 
> gettext looks like a very heavy-duty approach. (A lot of these third
> party solutions are. My experience was that a third party library that
> took care of 5% of the functionality of my application, would be several
> times bigger than my entire app.)

gettext /is/ a heavy-duty approach.  It is designed to separate the
program code and that translation texts, so that they can be written by
different people, compiled separately, distributed separately, and (if
desired) updated separately - because the binary and the translation
files are all separate files.  It is a very useful approach for many
kinds of program - but too big and complex for what the OP wants, I believe.

> 
> The method is basically this, assuming you have tables of messages for
> all languages in memory:
> 
> * Take an English message M
> * Look it up in the English table, to get index N (with 100 messages,
>   a linear search will do)
> * If N is in range, return the string from table[N] for language L
> * If M wasn't found, just return M, the English version.
> 
> So, probably a 10 or 20 line function.

That can be okay for a starting point, but it has a /big/ problem - you
only get one entry for each original English language message.  When you
are translating messages, it is not uncommon to encounter different
messages with the same text in the original language but different texts
in the translations.  In gettext, this is done by including __FILE__ and
__LINE__ in the lookup.

> 
> This would require two copies of each English message, one in the
> source, and one in a searchable table. And that needs maintenance.
> 
> You might be able to get around that by embedding a serial number in
> each English message:
> 
>    puts(_("Please enter filename: !078"));
> 
> Here the '!078" is the number and does not appear (or you can use {78}
> etc, any scheme will do).

Maintenance of the string numbers here is a hassle.

> 
> Now you just have to search the table for language L for a message with
> the same number. (You don't need to convert to an integer, just compare
> the last few characters.)
> 
> Of course, you need to return a string without the !078 etc in it. For
> that purpose, it might be better to put this number at the start. Then
> you return a string pointing to the just past the number.
> 
> (See example below using such a scheme. This might give some ideas.)
> 
> You can use the number as an actual index, but the maintenance becomes
> harder.
> 
> There is still the problem of producing a list of English messages for
> translators to work from. But the format and ordering of that is not
> critical.
> 
>>> (Any licensing issues are left as an exercise.)
>>
>> And this is another good point to study.
> 
> Another reason to forget using anyone else's library.

No, it is another reason to look at the licensing before using other
libraries.  People write libraries with the intention of letting other
people use them - you just need to make sure the licensing is suitable.

[toc] | [prev] | [next] | [standalone]


#27281

Frombartc <bc@freeuk.com>
Date2017-09-08 14:48 +0100
Message-ID<YcxsB.683027$uh.279777@fx28.am4>
In reply to#27278
On 08/09/2017 12:37, David Brown wrote:
> On 08/09/17 12:32, bartc wrote:

>> The method is basically this, assuming you have tables of messages for
>> all languages in memory:
>>
>> * Take an English message M
>> * Look it up in the English table, to get index N (with 100 messages,
>>    a linear search will do)
>> * If N is in range, return the string from table[N] for language L
>> * If M wasn't found, just return M, the English version.
>>
>> So, probably a 10 or 20 line function.
> 
> That can be okay for a starting point, but it has a /big/ problem - you
> only get one entry for each original English language message.  When you
> are translating messages, it is not uncommon to encounter different
> messages with the same text in the original language but different texts
> in the translations.  In gettext, this is done by including __FILE__ and
> __LINE__ in the lookup.

The OP said there are 50-100 messages. Then any clashes (of the same 
English text with different meanings) can be handled manually.

But my scheme with references numbers can fix that. That can be extended 
to annotate messages give a general method of disambiguating messages 
with multiple meanings.

>>
>> This would require two copies of each English message, one in the
>> source, and one in a searchable table. And that needs maintenance.
>>
>> You might be able to get around that by embedding a serial number in
>> each English message:
>>
>>     puts(_("Please enter filename: !078"));
>>
>> Here the '!078" is the number and does not appear (or you can use {78}
>> etc, any scheme will do).
> 
> Maintenance of the string numbers here is a hassle.

No, the numbers can be anything, including any text, or can be 
annotations. But in this scheme, every message must have an annotation, 
and that will can the appearance of the message within the source.


>> Another reason to forget using anyone else's library.
> 
> No, it is another reason to look at the licensing before using other
> libraries.  People write libraries with the intention of letting other
> people use them - you just need to make sure the licensing is suitable.

How does that library deal with the issues of extracting the messages in 
a format that can be submitted to a translator (who might be in a 
different country), and what format are they sent back in, or submitted 
to the program?

What about when the program is revised, and messages are deleted, added 
or modified?

How does it deal with multiple instances of the same message that differ 
only in leading or trailing punctuation or capitalisation? Do multiple 
messages have to be provided?

What about the problem raised above of the same English words having a 
different meaning depending on context?

I looked at docs for gettext and it's a 275 pages in PDF format; 378 
pages in Word. How many messages did the OP want to deal with again?

(The scheme I outlined in my first post in the thread dealt with all 
this. And it totalled a few hundred lines of code. Actually I don't 
think I needed the translations at all; they could be loaded locally 
from a file, with an existing version of the application, so no 
intervention was needed.)

-- 
bartc

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.arch.embedded


csiph-web