diff options
author | Tom Ross <midgey@rockbox.org> | 2009-10-18 00:56:42 +0000 |
---|---|---|
committer | Tom Ross <midgey@rockbox.org> | 2009-10-18 00:56:42 +0000 |
commit | ec2737b2c24ac442d2b9fcf0f0222becb456d8ce (patch) | |
tree | a375c87ad5236558ded8169e4065b24a377875fc | |
parent | bde02318035b9cad07a288b611f2b77fdf9cf1f8 (diff) | |
download | rockbox-ec2737b2c24ac442d2b9fcf0f0222becb456d8ce.tar.gz rockbox-ec2737b2c24ac442d2b9fcf0f0222becb456d8ce.zip |
Change the .lng files to contain strings from multiple users. Still hard-coded to only output the core strings for now. Should be the majority of the core changes needed for translatable plugins.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23241 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/filetree.c | 2 | ||||
-rw-r--r-- | apps/lang/lang.make | 7 | ||||
-rw-r--r-- | apps/language.c | 78 | ||||
-rw-r--r-- | apps/language.h | 7 | ||||
-rw-r--r-- | apps/main.c | 6 | ||||
-rw-r--r-- | apps/settings.c | 2 | ||||
-rwxr-xr-x | tools/genlang | 61 |
7 files changed, 108 insertions, 55 deletions
diff --git a/apps/filetree.c b/apps/filetree.c index 8fbc39fa67..3468051b55 100644 --- a/apps/filetree.c +++ b/apps/filetree.c | |||
@@ -526,7 +526,7 @@ int ft_enter(struct tree_context* c) | |||
526 | 526 | ||
527 | case FILE_ATTR_LNG: | 527 | case FILE_ATTR_LNG: |
528 | splash(0, ID2P(LANG_WAIT)); | 528 | splash(0, ID2P(LANG_WAIT)); |
529 | if(!lang_load(buf)) { | 529 | if(!lang_core_load(buf)) { |
530 | set_file(buf, (char *)global_settings.lang_file, | 530 | set_file(buf, (char *)global_settings.lang_file, |
531 | MAX_FILENAME); | 531 | MAX_FILENAME); |
532 | talk_init(); /* use voice of same language */ | 532 | talk_init(); /* use voice of same language */ |
diff --git a/apps/lang/lang.make b/apps/lang/lang.make index e32f084a29..f7366c9225 100644 --- a/apps/lang/lang.make +++ b/apps/lang/lang.make | |||
@@ -18,9 +18,14 @@ CLEANOBJS += $(BUILDDIR)/lang/max_language_size.h $(BUILDDIR)/lang/lang* | |||
18 | # Therefore we create it here. | 18 | # Therefore we create it here. |
19 | #DUMMY := $(shell mkdir -p $(BUILDDIR)/apps/lang) | 19 | #DUMMY := $(shell mkdir -p $(BUILDDIR)/apps/lang) |
20 | 20 | ||
21 | # Calculate the maximum language size. Currently based on the file size | ||
22 | # of the largest lng file. Subtract 10 due to HEADER_SIZE and | ||
23 | # SUBHEADER_SIZE. | ||
24 | # TODO: In the future generate this file within genlang or another script | ||
25 | # in order to only calculate the maximum size based on the core strings. | ||
21 | $(BUILDDIR)/lang/max_language_size.h: $(LANGOBJ) | 26 | $(BUILDDIR)/lang/max_language_size.h: $(LANGOBJ) |
22 | $(call PRINTS,Create $(notdir $@)) | 27 | $(call PRINTS,Create $(notdir $@)) |
23 | $(SILENT)echo "#define MAX_LANGUAGE_SIZE `ls -ln $(BUILDDIR)/apps/lang/* | awk '{print $$5}' | sort -n | tail -1`" > $@ | 28 | $(SILENT)echo "#define MAX_LANGUAGE_SIZE `ls -ln $(BUILDDIR)/apps/lang/* | awk '{print $$5-10}' | sort -n | tail -1`" > $@ |
24 | 29 | ||
25 | $(BUILDDIR)/lang/lang_core.o: $(APPSDIR)/lang/$(LANGUAGE).lang $(BUILDDIR)/apps/features | 30 | $(BUILDDIR)/lang/lang_core.o: $(APPSDIR)/lang/$(LANGUAGE).lang $(BUILDDIR)/apps/features |
26 | $(SILENT)for f in `cat $(BUILDDIR)/apps/features`; do feat="$$feat:$$f" ; done; \ | 31 | $(SILENT)for f in `cat $(BUILDDIR)/apps/features`; do feat="$$feat:$$f" ; done; \ |
diff --git a/apps/language.c b/apps/language.c index fe9ad5e97d..70549e194d 100644 --- a/apps/language.c +++ b/apps/language.c | |||
@@ -37,10 +37,11 @@ | |||
37 | /* These defines must match the initial bytes in the binary lang file */ | 37 | /* These defines must match the initial bytes in the binary lang file */ |
38 | /* See tools/genlang (TODO: Use common include for both) */ | 38 | /* See tools/genlang (TODO: Use common include for both) */ |
39 | #define LANGUAGE_COOKIE 0x1a | 39 | #define LANGUAGE_COOKIE 0x1a |
40 | #define LANGUAGE_VERSION 0x05 | 40 | #define LANGUAGE_VERSION 0x06 |
41 | #define LANGUAGE_FLAG_RTL 0x01 | 41 | #define LANGUAGE_FLAG_RTL 0x01 |
42 | 42 | ||
43 | #define HEADER_SIZE 4 | 43 | #define HEADER_SIZE 4 |
44 | #define SUBHEADER_SIZE 6 | ||
44 | 45 | ||
45 | static unsigned char language_buffer[MAX_LANGUAGE_SIZE]; | 46 | static unsigned char language_buffer[MAX_LANGUAGE_SIZE]; |
46 | static unsigned char lang_options = 0; | 47 | static unsigned char lang_options = 0; |
@@ -54,52 +55,62 @@ void lang_init(const unsigned char *builtin, unsigned char **dest, int count) | |||
54 | } | 55 | } |
55 | } | 56 | } |
56 | 57 | ||
57 | int lang_load(const char *filename) | 58 | int lang_load(const char *filename, const unsigned char *builtin, |
59 | unsigned char **dest, unsigned char *buffer, | ||
60 | unsigned int user_num, int max_lang_size, | ||
61 | unsigned int max_id) | ||
58 | { | 62 | { |
59 | int fsize; | 63 | int lang_size; |
60 | int fd = open(filename, O_RDONLY); | 64 | int fd = open(filename, O_RDONLY); |
61 | int retcode=0; | 65 | int retcode=0; |
62 | unsigned char lang_header[HEADER_SIZE]; | 66 | unsigned char lang_header[HEADER_SIZE]; |
67 | unsigned char sub_header[SUBHEADER_SIZE]; | ||
68 | unsigned int id, num_strings, foffset; | ||
69 | |||
63 | if(fd < 0) | 70 | if(fd < 0) |
64 | return 1; | 71 | return 1; |
65 | fsize = filesize(fd) - HEADER_SIZE; | 72 | read(fd, lang_header, HEADER_SIZE); |
66 | if(fsize <= MAX_LANGUAGE_SIZE) { | 73 | if((lang_header[0] == LANGUAGE_COOKIE) && |
67 | read(fd, lang_header, HEADER_SIZE); | 74 | (lang_header[1] == LANGUAGE_VERSION) && |
68 | if((lang_header[0] == LANGUAGE_COOKIE) && | 75 | (lang_header[2] == TARGET_ID)) { |
69 | (lang_header[1] == LANGUAGE_VERSION) && | 76 | /* jump to the proper entry in the table of subheaders */ |
70 | (lang_header[2] == TARGET_ID)) { | 77 | lseek(fd, user_num * SUBHEADER_SIZE, SEEK_CUR); |
71 | read(fd, language_buffer, MAX_LANGUAGE_SIZE); | 78 | read(fd, sub_header, SUBHEADER_SIZE); |
72 | unsigned char *ptr = language_buffer; | 79 | /* read in information about the requested lang */ |
73 | int id; | 80 | num_strings = (sub_header[0]<<8) | sub_header[1]; |
81 | lang_size = (sub_header[2]<<8) | sub_header[3]; | ||
82 | foffset = (sub_header[4]<<8) | sub_header[5]; | ||
83 | if(lang_size <= max_lang_size) { | ||
74 | /* initialize with builtin */ | 84 | /* initialize with builtin */ |
75 | lang_init(language_builtin, language_strings, | 85 | lang_init(builtin, dest, num_strings); |
76 | LANG_LAST_INDEX_IN_ARRAY); | 86 | lseek(fd, foffset, SEEK_SET); |
87 | read(fd, buffer, lang_size); | ||
77 | 88 | ||
78 | while(fsize>3) { | 89 | while(lang_size>3) { |
79 | id = (ptr[0]<<8) | ptr[1]; /* get two-byte id */ | 90 | id = ((buffer[0]<<8) | buffer[1]); /* get two-byte id */ |
80 | ptr+=2; /* pass the id */ | 91 | buffer += 2; /* pass the id */ |
81 | if(id < LANG_LAST_INDEX_IN_ARRAY) { | 92 | if(id < max_id) { |
82 | #if 0 | 93 | #if 0 |
83 | DEBUGF("%2x New: %30s ", id, ptr); | 94 | DEBUGF("%2x New: %30s ", id, buffer); |
84 | DEBUGF("Replaces: %s\n", language_strings[id]); | 95 | DEBUGF("Replaces: %s\n", dest[id]); |
85 | #endif | 96 | #endif |
86 | language_strings[id] = ptr; /* point to this string */ | 97 | dest[id] = buffer; /* point to this string */ |
87 | } | ||
88 | while(*ptr) { /* pass the string */ | ||
89 | fsize--; | ||
90 | ptr++; | ||
91 | } | 98 | } |
92 | fsize-=3; /* the id and the terminating zero */ | 99 | while(*buffer) { /* pass the string */ |
93 | ptr++; /* pass the terminating zero-byte */ | 100 | lang_size--; |
101 | buffer++; | ||
102 | } | ||
103 | lang_size-=3; /* the id and the terminating zero */ | ||
104 | buffer++; /* pass the terminating zero-byte */ | ||
94 | } | 105 | } |
95 | } | 106 | } |
96 | else { | 107 | else { |
97 | DEBUGF("Illegal language file\n"); | 108 | DEBUGF("Language %s too large: %d\n", filename, lang_size); |
98 | retcode = 2; | 109 | retcode = 2; |
99 | } | 110 | } |
100 | } | 111 | } |
101 | else { | 112 | else { |
102 | DEBUGF("Language %s too large: %d\n", filename, fsize); | 113 | DEBUGF("Illegal language file\n"); |
103 | retcode = 3; | 114 | retcode = 3; |
104 | } | 115 | } |
105 | close(fd); | 116 | close(fd); |
@@ -107,10 +118,17 @@ int lang_load(const char *filename) | |||
107 | return retcode; | 118 | return retcode; |
108 | } | 119 | } |
109 | 120 | ||
121 | int lang_core_load(const char *filename) | ||
122 | { | ||
123 | return lang_load(filename, core_language_builtin, language_strings, | ||
124 | language_buffer, 0, MAX_LANGUAGE_SIZE, | ||
125 | LANG_LAST_INDEX_IN_ARRAY); | ||
126 | } | ||
127 | |||
110 | int lang_english_to_id(const char *english) | 128 | int lang_english_to_id(const char *english) |
111 | { | 129 | { |
112 | int i; | 130 | int i; |
113 | unsigned char *ptr = (unsigned char *) language_builtin; | 131 | unsigned char *ptr = (unsigned char *) core_language_builtin; |
114 | 132 | ||
115 | for (i = 0; i < LANG_LAST_INDEX_IN_ARRAY; i++) { | 133 | for (i = 0; i < LANG_LAST_INDEX_IN_ARRAY; i++) { |
116 | if (!strcmp(ptr, english)) | 134 | if (!strcmp(ptr, english)) |
diff --git a/apps/language.h b/apps/language.h index 4cfe2b22ce..cbfa7e2c1d 100644 --- a/apps/language.h +++ b/apps/language.h | |||
@@ -25,7 +25,12 @@ | |||
25 | void lang_init(const unsigned char *builtin, unsigned char **dest, int count); | 25 | void lang_init(const unsigned char *builtin, unsigned char **dest, int count); |
26 | 26 | ||
27 | /* load a given language file */ | 27 | /* load a given language file */ |
28 | int lang_load(const char *filename); | 28 | int lang_core_load(const char *filename); |
29 | |||
30 | int lang_load(const char *filename, const unsigned char *builtin, | ||
31 | unsigned char **dest, unsigned char *buffer, | ||
32 | unsigned int user_num, int max_lang_size, | ||
33 | unsigned int max_id); | ||
29 | 34 | ||
30 | /* get the ID of an english string so it can be localised */ | 35 | /* get the ID of an english string so it can be localised */ |
31 | int lang_english_to_id(const char *english); | 36 | int lang_english_to_id(const char *english); |
diff --git a/apps/main.c b/apps/main.c index 3c93b4fea4..ec4829189b 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -308,7 +308,8 @@ static void init(void) | |||
308 | button_init(); | 308 | button_init(); |
309 | backlight_init(); | 309 | backlight_init(); |
310 | sim_tasks_init(); | 310 | sim_tasks_init(); |
311 | lang_init(language_builtin, language_strings, LANG_LAST_INDEX_IN_ARRAY); | 311 | lang_init(core_language_builtin, language_strings, |
312 | LANG_LAST_INDEX_IN_ARRAY); | ||
312 | #ifdef DEBUG | 313 | #ifdef DEBUG |
313 | debug_init(); | 314 | debug_init(); |
314 | #endif | 315 | #endif |
@@ -399,7 +400,8 @@ static void init(void) | |||
399 | font_init(); | 400 | font_init(); |
400 | 401 | ||
401 | show_logo(); | 402 | show_logo(); |
402 | lang_init(language_builtin, language_strings, LANG_LAST_INDEX_IN_ARRAY); | 403 | lang_init(core_language_builtin, language_strings, |
404 | LANG_LAST_INDEX_IN_ARRAY); | ||
403 | 405 | ||
404 | #ifdef DEBUG | 406 | #ifdef DEBUG |
405 | debug_init(); | 407 | debug_init(); |
diff --git a/apps/settings.c b/apps/settings.c index 2a5e31824f..6cbd559f94 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -900,7 +900,7 @@ void settings_apply(bool read_disk) | |||
900 | if ( global_settings.lang_file[0]) { | 900 | if ( global_settings.lang_file[0]) { |
901 | snprintf(buf, sizeof buf, LANG_DIR "/%s.lng", | 901 | snprintf(buf, sizeof buf, LANG_DIR "/%s.lng", |
902 | global_settings.lang_file); | 902 | global_settings.lang_file); |
903 | lang_load(buf); | 903 | lang_core_load(buf); |
904 | talk_init(); /* use voice of same language */ | 904 | talk_init(); /* use voice of same language */ |
905 | } | 905 | } |
906 | 906 | ||
diff --git a/tools/genlang b/tools/genlang index c5fb403801..6f00365716 100755 --- a/tools/genlang +++ b/tools/genlang | |||
@@ -13,9 +13,12 @@ | |||
13 | # See apps/language.c (TODO: Use common include for both) | 13 | # See apps/language.c (TODO: Use common include for both) |
14 | # Cookie and binary version for the binary lang file | 14 | # Cookie and binary version for the binary lang file |
15 | my $LANGUAGE_COOKIE = 0x1a; | 15 | my $LANGUAGE_COOKIE = 0x1a; |
16 | my $LANGUAGE_VERSION = 0x05; | 16 | my $LANGUAGE_VERSION = 0x06; |
17 | my $LANGUAGE_FLAG_RTL = 0x01; | 17 | my $LANGUAGE_FLAG_RTL = 0x01; |
18 | 18 | ||
19 | my $HEADER_SIZE = 4; | ||
20 | my $SUBHEADER_SIZE = 6; | ||
21 | |||
19 | # A note for future users and readers: The original v1 language system allowed | 22 | # A note for future users and readers: The original v1 language system allowed |
20 | # the build to create and use a different language than english built-in. We | 23 | # the build to create and use a different language than english built-in. We |
21 | # removed that feature from our build-system, but the build scripts still had | 24 | # removed that feature from our build-system, but the build scripts still had |
@@ -385,7 +388,7 @@ sub compare { | |||
385 | my @idcount; # counter for lang ID numbers | 388 | my @idcount; # counter for lang ID numbers |
386 | my @voiceid; # counter for voice-only ID numbers | 389 | my @voiceid; # counter for voice-only ID numbers |
387 | 390 | ||
388 | foreach $i (keys %users) { | 391 | for (keys %users) { |
389 | push @idcount, 0; | 392 | push @idcount, 0; |
390 | push @voiceid, 0x8000; | 393 | push @voiceid, 0x8000; |
391 | } | 394 | } |
@@ -613,7 +616,7 @@ if($prefix) { | |||
613 | It will be initialized at runtime. */ | 616 | It will be initialized at runtime. */ |
614 | extern unsigned char *language_strings[]; | 617 | extern unsigned char *language_strings[]; |
615 | /* this contains the concatenation of all strings, separated by \\0 chars */ | 618 | /* this contains the concatenation of all strings, separated by \\0 chars */ |
616 | extern const unsigned char language_builtin[]; | 619 | extern const unsigned char core_language_builtin[]; |
617 | 620 | ||
618 | /* The enum below contains all available strings */ | 621 | /* The enum below contains all available strings */ |
619 | enum \{ | 622 | enum \{ |
@@ -627,18 +630,18 @@ MOO | |||
627 | #include "$headername" | 630 | #include "$headername" |
628 | 631 | ||
629 | unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY]; | 632 | unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY]; |
630 | const unsigned char language_builtin[] = | 633 | const unsigned char core_language_builtin[] = |
631 | MOO | 634 | MOO |
632 | ; | 635 | ; |
633 | 636 | ||
634 | # Output the ID names for the enum in the header file | 637 | # Output the ID names for the enum in the header file |
635 | my $i; | 638 | my $i; |
636 | for $i (1 .. $idcount[$users{"core"}]) { | 639 | for $i (0 .. $idcount[$users{"core"}]-1) { |
637 | my $name=$idnum[$users{"core"}][$i - 1]; # get the ID name | 640 | my $name=$idnum[$users{"core"}][$i]; # get the ID name |
638 | 641 | ||
639 | $name =~ s/\"//g; # cut off the quotes | 642 | $name =~ s/\"//g; # cut off the quotes |
640 | 643 | ||
641 | printf HFILE_CORE (" %s, /* %d */\n", $name, $i-1); | 644 | printf HFILE_CORE (" %s, /* %d */\n", $name, $i); |
642 | } | 645 | } |
643 | 646 | ||
644 | # Output separation marker for last string ID and the upcoming voice IDs | 647 | # Output separation marker for last string ID and the upcoming voice IDs |
@@ -663,8 +666,8 @@ MOO | |||
663 | print HFILE_CORE "\n};\n/* end of generated enum list */\n"; | 666 | print HFILE_CORE "\n};\n/* end of generated enum list */\n"; |
664 | 667 | ||
665 | # Output the target phrases for the source file | 668 | # Output the target phrases for the source file |
666 | for $i (1 .. $idcount[$users{"core"}]) { | 669 | for $i (0 .. $idcount[$users{"core"}]-1) { |
667 | my $name=$idnum[$users{"core"}][$i - 1]; # get the ID | 670 | my $name=$idnum[$users{"core"}][$i]; # get the ID |
668 | my $dest = $dest{$name}; # get the destination phrase | 671 | my $dest = $dest{$name}; # get the destination phrase |
669 | 672 | ||
670 | $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote | 673 | $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote |
@@ -700,18 +703,32 @@ elsif($binary) { | |||
700 | printf OUTF ("%c%c%c%c", $LANGUAGE_COOKIE, $LANGUAGE_VERSION, $target_id, | 703 | printf OUTF ("%c%c%c%c", $LANGUAGE_COOKIE, $LANGUAGE_VERSION, $target_id, |
701 | $langoptions); # magic lang file header | 704 | $langoptions); # magic lang file header |
702 | 705 | ||
703 | # loop over the target phrases | 706 | # output the number of strings for each user |
704 | for $i (1 .. $idcount[$users{"core"}]) { | 707 | my $foffset = $HEADER_SIZE + $SUBHEADER_SIZE * keys(%users); |
705 | my $name=$idnum[$users{"core"}][$i - 1]; # get the ID | 708 | for (keys %users) { |
706 | my $dest = $dest{$name}; # get the destination phrase | 709 | my $size; |
710 | for $n (0 .. $idcount[$_]-1) { | ||
711 | $size += length(trim($dest{$idnum[$_][$n]})) + 1; | ||
712 | } | ||
713 | printf OUTF ("%c%c%c%c%c%c", ($idcount[$_] >> 8), ($idcount[$_] & 0xff), | ||
714 | ($size >> 8), ($size & 0xff), ($foffset >> 8), ($foffset & 0xff)); | ||
715 | $foffset += $size; | ||
716 | } | ||
707 | 717 | ||
708 | if($dest) { | 718 | for (keys %users) { |
709 | $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes | 719 | # loop over the target phrases |
720 | for $n (0 .. $idcount[$_]-1) { | ||
721 | my $name=$idnum[$_][$n]; # get the ID | ||
722 | my $dest = $dest{$name}; # get the destination phrase | ||
710 | 723 | ||
711 | # Now, make sure we get the number from the english sort order: | 724 | if($dest) { |
712 | $idnum = $idmap[$users{"core"}]{$name}; | 725 | $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes |
713 | 726 | ||
714 | printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest); | 727 | # Now, make sure we get the number from the english sort order: |
728 | $idnum = $idmap[$_]{$name}; | ||
729 | |||
730 | printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest); | ||
731 | } | ||
715 | } | 732 | } |
716 | } | 733 | } |
717 | } | 734 | } |
@@ -770,7 +787,13 @@ elsif($voiceout) { | |||
770 | 787 | ||
771 | 788 | ||
772 | if($verbose) { | 789 | if($verbose) { |
773 | printf("%d ID strings scanned\n", $idcount[$users{"core"}]); | 790 | my $num_str = 0; |
791 | |||
792 | for (keys %users) { | ||
793 | $num_str += $idcount[$_]; | ||
794 | } | ||
795 | |||
796 | printf("%d ID strings scanned\n", $num_str); | ||
774 | 797 | ||
775 | print "* head *\n"; | 798 | print "* head *\n"; |
776 | for(keys %head) { | 799 | for(keys %head) { |