Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #27232 > unrolled thread
| Started by | pozz <pozzugno@gmail.com> |
|---|---|
| First post | 2017-09-05 09:30 +0200 |
| Last post | 2017-09-08 17:33 +0000 |
| Articles | 20 on this page of 23 — 14 participants |
Back to article view | Back to comp.arch.embedded
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 →
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2017-09-05 09:30 +0200 |
| Subject | Multi-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | raltbos@xs4all.nl (Richard Bos) |
|---|---|
| Date | 2017-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]
| From | Robert Wessel <robertwessel2@yahoo.com> |
|---|---|
| Date | 2017-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]
| From | raltbos@xs4all.nl (Richard Bos) |
|---|---|
| Date | 2017-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]
| From | Allan Herriman <allanherriman@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | Paul <paul@pcserviceselectronics.co.uk> |
|---|---|
| Date | 2017-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]
| From | Theo Markettos <theom+news@chiark.greenend.org.uk> |
|---|---|
| Date | 2017-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]
| From | Phil Hobbs <pcdhSpamMeSenseless@electrooptical.net> |
|---|---|
| Date | 2017-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]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-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]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2017-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]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2017-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]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-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]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-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]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-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