diff options
author | PavelSindler <sindlerpa@gmail.com> | 2017-12-02 23:56:39 +0300 |
---|---|---|
committer | PavelSindler <sindlerpa@gmail.com> | 2017-12-02 23:56:39 +0300 |
commit | 22065e48773a98886f8a71d0a43b3b662bb7b0e2 (patch) | |
tree | ec291ea3ad2f19e82ab17344b0e75b255824cd11 /Firmware/langtool.pl | |
parent | 986b2868032a3cfcc94b7e07143d58e6b1eb58d8 (diff) | |
parent | 26cdb75cf7f69bdc7412217228164ead170a09ba (diff) |
merging from dev/MK3
Diffstat (limited to 'Firmware/langtool.pl')
-rw-r--r-- | Firmware/langtool.pl | 251 |
1 files changed, 224 insertions, 27 deletions
diff --git a/Firmware/langtool.pl b/Firmware/langtool.pl index a689f3b83..a91af44de 100644 --- a/Firmware/langtool.pl +++ b/Firmware/langtool.pl @@ -4,53 +4,168 @@ use strict; use warnings; -my @langs = ("en","cz","it","es","pl"); +#my @langs = ("en","cz","it","es","de"); +my @langs = ("en","cz"); sub parselang { my ($filename) = @_; open(my $fh, '<:encoding(UTF-8)', $filename) +# open(my $fh, '<', $filename) or die "Could not open file '$filename' $!"; # Create a new hash reference. my $out = {}; while (my $line = <$fh>) { chomp $line; - next if (index($line, 'MSG') == -1); - $line =~ /(?is)\#define\s*(\S*)\s*(.*)/; - my $symbol = $1; - my $v = $2; + next if (index($line, 'define') == -1 || index($line, 'MSG') == -1); + my $modifiers = {}; + my $symbol = ''; + my $value = ''; + if (index($line, 'define(') == -1) { + # Extended definition, which specifies the string formatting. + $line =~ /(?is)define\s*(\S*)\s*(.*)/; + $symbol = "$1"; + $value = $2; + } else { + $line =~ /(?is)define\((.*)\)\s*(\S*)\s*(.*)/; + my $options = $1; + foreach my $key_value (split /,/, $options) { + if ($key_value =~ /\s*(\S*)\s*=\s*(\S*)\s*/) { + ${$modifiers}{$1} = $2; + } + } + $symbol = "$2"; + $value = $3; + } next if (! defined $symbol or length($symbol) == 0); # Trim whitespaces from both sides - $v =~ s/^\s+|\s+$//g; + $value =~ s/^\s+|\s+$//g; #$string =~ s/" MACHINE_NAME "/Prusa i3/; - $v =~ s/" FIRMWARE_URL "/https:\/\/github.com\/prusa3d\/Prusa-i3-Plus\//; - $v =~ s/" PROTOCOL_VERSION "/1.0/; - $v =~ s/" STRINGIFY\(EXTRUDERS\) "/1/; - $v =~ s/" MACHINE_UUID "/00000000-0000-0000-0000-000000000000/; - ${$out}{$symbol} = $v; + $value =~ s/" FIRMWARE_URL "/https:\/\/github.com\/prusa3d\/Prusa-i3-Plus\//; + $value =~ s/" PROTOCOL_VERSION "/1.0/; + $value =~ s/" STRINGIFY\(EXTRUDERS\) "/1/; + $value =~ s/" MACHINE_UUID "/00000000-0000-0000-0000-000000000000/; + ${$out}{$symbol} = { value=>$value, %$modifiers }; } return $out; } +sub pgm_is_whitespace +{ + my ($c) = @_; + if (! defined($c)) { + print "pgm_is_whitespace: undefined\n"; + exit(1); + } + return $c == ord(' ') || $c == ord('\t') || $c == ord('\r') || $c == ord('\n'); +} + +sub pgm_is_interpunction +{ + my ($c) = @_; + return $c == ord('.') || $c == ord(',') || $c == ord(':') || $c == ord(';') || $c == ord('?') || $c == ord('!') || $c == ord('/'); +} + +sub break_text_fullscreen +{ + my $lines = []; + my ($text_str, $max_linelen) = @_; + if (! defined($text_str) || length($text_str) < 2) { + return $lines; + } + $text_str =~ s/^"//; + $text_str =~ s/([^\\])"/$1/; + $text_str =~ s/\\"/"/; + + my @msg = unpack("W*", $text_str); + #my @msg = split("", $text_str); + my $len = $#msg + 1; + my $i = 0; + + LINE: + while ($i < $len) { + while ($i < $len && pgm_is_whitespace($msg[$i])) { + $i += 1; + } + if ($i == $len) { + # End of the message. + last LINE; + } + my $msgend2 = $i + (($max_linelen > $len) ? $len : $max_linelen); + my $msgend = $msgend2; + if ($msgend < $len && ! pgm_is_whitespace($msg[$msgend]) && ! pgm_is_interpunction($msg[$msgend])) { + # Splitting a word. Find the start of the current word. + while ($msgend > $i && ! pgm_is_whitespace($msg[$msgend - 1])) { + $msgend -= 1; + } + if ($msgend == $i) { + # Found a single long word, which cannot be split. Just cut it. + $msgend = $msgend2; + } + } + my $outstr = substr($text_str, $i, $msgend - $i); + $i = $msgend; + $outstr =~ s/~/ /g; + #print "Output string: $outstr \n"; + push @$lines, $outstr; + } + + return $lines; +} + my %texts; +my %attributes; my $num_languages = 0; +if (1) +{ + # First load the common strings. + my $symbols = parselang("language_common.h"); + foreach my $key (keys %{$symbols}) { + if (! (exists $texts{$key})) { + my $symbol_value = ${$symbols}{$key}; + # Store the symbol value for each language. + $texts{$key} = [ (${$symbol_value}{value}) x ($#langs+1) ]; + # Store the possible attributes. + delete ${$symbol_value}{value}; + # Store an "is common" attribute. + ${$symbol_value}{common} = 1; + # 4x 80 characters, 4 lines sent over serial line. + ${$symbol_value}{length} = 320; + ${$symbol_value}{lines} = 1; + $attributes{$key} = $symbol_value; + } else { + print "Duplicate key in language_common.h: $key\n"; + } + } +} foreach my $lang (@langs) { my $symbols = parselang("language_$lang.h"); foreach my $key (keys %{$symbols}) { if (! (exists $texts{$key})) { $texts{$key} = []; } + my $symbol_value = ${$symbols}{$key}; my $strings = $texts{$key}; - die "Symbol $key defined first in $lang, undefined in the preceding language files." - if (scalar(@$strings) != $num_languages); - push @$strings, ${$symbols}{$key}; + if (defined $attributes{$key} && defined ${$attributes{$key}}{common} && ${$attributes{$key}}{common} == 1) { + # Common overrides the possible definintions in the language specific files. + } else { + die "Symbol $key defined first in $lang, undefined in the preceding language files." + if (scalar(@$strings) != $num_languages); + push @$strings, ${$symbol_value}{value}; + if ($lang eq 'en') { + # The english texts may contain attributes. Store them into %attributes. + delete ${$symbol_value}{value}; + $attributes{$key} = $symbol_value; + } + } } $num_languages += 1; foreach my $key (keys %texts) { my $strings = $texts{$key}; - if (scalar(@$strings) != $num_languages) { + if (scalar(@$strings) < $num_languages) { # die "Symbol $key undefined in $lang." - print "Symbol $key undefined in $lang. Using the english variant.\n"; + print "Symbol $key undefined in language \"$lang\". Using the english variant:\n"; + print "\t", ${$strings}[0], "\n"; push @$strings, ${$strings}[0]; } } @@ -66,8 +181,30 @@ print $fh <<END #ifndef LANGUAGE_ALL_H #define LANGUAGE_ALL_H -#define LANG_NUM (${num_languages}) +#include <avr/pgmspace.h> +// Language indices into their particular symbol tables. +END +; + +# Export symbolic IDs of languages. +for my $i (0 .. $#langs) { + my $lang = uc $langs[$i]; + print $fh "#define LANG_ID_$lang $i\n"; +} +print $fh <<END +// Language is not defined and it shall be selected from the menu. +#define LANG_ID_FORCE_SELECTION 254 +// Language is not defined on a virgin RAMBo board. +#define LANG_ID_UNDEFINED 255 + +// Default language ID, if no language is selected. +#define LANG_ID_DEFAULT LANG_ID_CZ + +// Number of languages available in the language table. +#define LANG_NUM ${num_languages} + +// Currectly active language selection. extern unsigned char lang_selected; #define LANG_TABLE_SELECT_EXPLICIT(TABLE, LANG) ((const char*)(pgm_read_ptr(TABLE + (LANG)))) @@ -77,10 +214,17 @@ END ; foreach my $key (sort(keys %texts)) { - print $fh "extern const char* const ${key}_LANG_TABLE[LANG_NUM];\n"; - print $fh "#define $key LANG_TABLE_SELECT(${key}_LANG_TABLE)\n"; - print $fh "#define ${key}_EXPLICIT(LANG) LANG_TABLE_SELECT_EXPLICIT(${key}_LANG_TABLE, LANG)\n" - if ($key eq "MSG_LANGUAGE_NAME" || $key eq "MSG_LANGUAGE_SELECT"); + my $strings = $texts{$key}; + if (@{$strings} == grep { $_ eq ${$strings}[0] } @{$strings}) { + # All strings are English. + print $fh "extern const char* const ${key}_LANG_TABLE[1];\n"; + print $fh "#define $key LANG_TABLE_SELECT_EXPLICIT(${key}_LANG_TABLE, 0)\n"; + } else { + print $fh "extern const char* const ${key}_LANG_TABLE[LANG_NUM];\n"; + print $fh "#define $key LANG_TABLE_SELECT(${key}_LANG_TABLE)\n"; + print $fh "#define ${key}_EXPLICIT(LANG) LANG_TABLE_SELECT_EXPLICIT(${key}_LANG_TABLE, LANG)\n" + if ($key eq "MSG_LANGUAGE_NAME" || $key eq "MSG_LANGUAGE_SELECT"); + } } print $fh <<END @@ -100,8 +244,8 @@ $filename = 'language_all.cpp'; open($fh, '>', $filename) or die "Could not open file '$filename' $!"; print $fh <<'END' -#include <avr/pgmspace.h> -#include "configuration_prusa.h" + +#include "Configuration_prusa.h" #include "language_all.h" #define LCD_WIDTH 20 @@ -110,16 +254,31 @@ extern unsigned char lang_selected; END ; -foreach my $key (sort(keys %texts)) { +my @keys = sort(keys %texts); +foreach my $key (@keys) { my $strings = $texts{$key}; + if (@{$strings} == grep { $_ eq ${$strings}[0] } @{$strings}) { + # Shrink the array to a single value. + $strings = [${$strings}[0]]; + } for (my $i = 0; $i <= $#{$strings}; $i ++) { my $suffix = uc($langs[$i]); - print $fh "const char ${key}_${suffix}[] PROGMEM = ${$strings}[$i];\n"; + if ($i == 0 || ${$strings}[$i] ne ${$strings}[0]) { + print $fh "const char ${key}_${suffix}[] PROGMEM = ${$strings}[$i];\n"; + } } - print $fh "const char * const ${key}_LANG_TABLE[LANG_NUM] PROGMEM = {\n"; + my $langnum = $#{$strings}+1; + if ($langnum == $#langs+1) { + $langnum = "LANG_NUM"; + } + print $fh "const char * const ${key}_LANG_TABLE[$langnum] PROGMEM = {\n"; for (my $i = 0; $i <= $#{$strings}; $i ++) { my $suffix = uc($langs[$i]); - print $fh "\t${key}_${suffix}"; + if ($i == 0 || ${$strings}[$i] ne ${$strings}[0]) { + print $fh "\t${key}_${suffix}"; + } else { + print $fh "\t${key}_EN"; + } print $fh ',' if $i < $#{$strings}; print $fh "\n"; } @@ -151,3 +310,41 @@ END ; print ".cpp created.\nDone!\n"; + +my $verify_only = 1; + +for my $lang (0 .. $#langs) { + print "Language: $langs[$lang]\n"; + foreach my $key (@keys) { + my $strings = $texts{$key}; + my %attrib = %{$attributes{$key}}; + my $message = ${$strings}[$lang]; + $message =~ /\S*"(.*)"\S*/; + $message = $1; + if ($lang == 0 || ${$strings}[0] ne $message) { + # If the language is not English, don't show the non-translated message. + my $max_nlines = $attrib{lines} // 1; + my $max_linelen = $attrib{length} // (($max_nlines > 1) ? 20 : 17); +# if (! $verify_only) { +# if ($nlines > 1) { +# print "Multi-line message: $message. Breaking to $nlines lines:\n"; +# print "\t$_\n" foreach (@{$lines}); +# } +# } + if ($max_nlines <= 1) { + my $linelen = length($message); + if ($linelen > $max_linelen) { + print "Key $key, language $langs[$lang], line length: $linelen, max length: $max_linelen\n"; + print "\t$message\n"; + } + } else { + my $lines = break_text_fullscreen($message, $max_linelen); + my $nlines = @{$lines}; + if ($nlines > $max_nlines) { + print "Key $key, language $langs[$lang], lines: $nlines, max lines: $max_nlines\n"; + print "\t$_\n" foreach (@{$lines}); + } + } + } + } +} |