Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
d8c986e0
Commit
d8c986e0
authored
Jan 04, 2011
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wrc: Add support for loading translations from po files.
parent
10700bf6
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
283 additions
and
0 deletions
+283
-0
po.c
tools/wrc/po.c
+268
-0
wrc.c
tools/wrc/wrc.c
+8
-0
wrc.h
tools/wrc/wrc.h
+1
-0
wrc.man.in
tools/wrc/wrc.man.in
+6
-0
No files found.
tools/wrc/po.c
View file @
d8c986e0
...
@@ -701,6 +701,270 @@ void write_po_files( const char *outname )
...
@@ -701,6 +701,270 @@ void write_po_files( const char *outname )
}
}
}
}
static
resource_t
*
new_top
,
*
new_tail
;
static
version_t
*
get_dup_version
(
language_t
*
lang
)
{
/* English "translations" take precedence over the original rc contents */
return
new_version
(
is_english
(
lang
)
?
1
:
-
1
);
}
static
name_id_t
*
dup_name_id
(
name_id_t
*
id
)
{
name_id_t
*
new
;
if
(
!
id
||
id
->
type
!=
name_str
)
return
id
;
new
=
new_name_id
();
*
new
=
*
id
;
new
->
name
.
s_name
=
convert_string
(
id
->
name
.
s_name
,
str_unicode
,
1252
);
return
new
;
}
static
resource_t
*
dup_resource
(
resource_t
*
res
,
language_t
*
lang
)
{
resource_t
*
new
=
xmalloc
(
sizeof
(
*
new
)
);
*
new
=
*
res
;
new
->
lan
=
lang
;
new
->
next
=
new
->
prev
=
NULL
;
new
->
name
=
dup_name_id
(
res
->
name
);
switch
(
res
->
type
)
{
case
res_dlg
:
new
->
res
.
dlg
=
xmalloc
(
sizeof
(
*
(
new
)
->
res
.
dlg
)
);
*
new
->
res
.
dlg
=
*
res
->
res
.
dlg
;
new
->
res
.
dlg
->
lvc
.
language
=
lang
;
new
->
res
.
dlg
->
lvc
.
version
=
get_dup_version
(
lang
);
break
;
case
res_men
:
new
->
res
.
men
=
xmalloc
(
sizeof
(
*
(
new
)
->
res
.
men
)
);
*
new
->
res
.
men
=
*
res
->
res
.
men
;
new
->
res
.
men
->
lvc
.
language
=
lang
;
new
->
res
.
men
->
lvc
.
version
=
get_dup_version
(
lang
);
break
;
case
res_stt
:
new
->
res
.
stt
=
xmalloc
(
sizeof
(
*
(
new
)
->
res
.
stt
)
);
*
new
->
res
.
stt
=
*
res
->
res
.
stt
;
new
->
res
.
stt
->
lvc
.
language
=
lang
;
new
->
res
.
stt
->
lvc
.
version
=
get_dup_version
(
lang
);
break
;
default:
assert
(
0
);
}
return
new
;
}
static
string_t
*
translate_string
(
po_file_t
po
,
string_t
*
str
,
int
*
found
)
{
po_message_t
msg
;
po_message_iterator_t
iterator
;
string_t
*
new
;
const
char
*
transl
;
int
res
;
char
*
buffer
,
*
msgid
,
*
context
;
if
(
!
str
->
size
||
!
(
buffer
=
convert_msgid_ascii
(
str
,
0
)))
return
convert_string
(
str
,
str_unicode
,
1252
);
msgid
=
buffer
;
context
=
get_message_context
(
&
msgid
);
msg
=
find_message
(
po
,
msgid
,
context
,
&
iterator
);
po_message_iterator_free
(
iterator
);
if
(
msg
)
(
*
found
)
++
;
transl
=
msg
?
po_message_msgstr
(
msg
)
:
msgid
;
new
=
xmalloc
(
sizeof
(
*
new
)
);
new
->
type
=
str_unicode
;
new
->
size
=
wine_utf8_mbstowcs
(
0
,
transl
,
strlen
(
transl
),
NULL
,
0
);
new
->
str
.
wstr
=
xmalloc
(
(
new
->
size
+
1
)
*
sizeof
(
WCHAR
)
);
res
=
wine_utf8_mbstowcs
(
MB_ERR_INVALID_CHARS
,
transl
,
strlen
(
transl
),
new
->
str
.
wstr
,
new
->
size
);
if
(
res
==
-
2
)
error
(
"Invalid utf-8 character in string '%s'
\n
"
,
transl
);
new
->
str
.
wstr
[
new
->
size
]
=
0
;
free
(
buffer
);
return
new
;
}
static
control_t
*
translate_controls
(
po_file_t
po
,
control_t
*
ctrl
,
int
*
found
)
{
control_t
*
new
,
*
head
=
NULL
,
*
tail
=
NULL
;
while
(
ctrl
)
{
new
=
xmalloc
(
sizeof
(
*
new
)
);
*
new
=
*
ctrl
;
if
(
control_has_title
(
ctrl
))
{
new
->
title
=
new_name_id
();
*
new
->
title
=
*
ctrl
->
title
;
new
->
title
->
name
.
s_name
=
translate_string
(
po
,
ctrl
->
title
->
name
.
s_name
,
found
);
}
else
new
->
title
=
dup_name_id
(
ctrl
->
title
);
new
->
ctlclass
=
dup_name_id
(
ctrl
->
ctlclass
);
if
(
tail
)
tail
->
next
=
new
;
else
head
=
new
;
new
->
next
=
NULL
;
new
->
prev
=
tail
;
tail
=
new
;
ctrl
=
ctrl
->
next
;
}
return
head
;
}
static
menu_item_t
*
translate_items
(
po_file_t
po
,
menu_item_t
*
item
,
int
*
found
)
{
menu_item_t
*
new
,
*
head
=
NULL
,
*
tail
=
NULL
;
while
(
item
)
{
new
=
xmalloc
(
sizeof
(
*
new
)
);
*
new
=
*
item
;
if
(
item
->
name
)
new
->
name
=
translate_string
(
po
,
item
->
name
,
found
);
if
(
item
->
popup
)
new
->
popup
=
translate_items
(
po
,
item
->
popup
,
found
);
if
(
tail
)
tail
->
next
=
new
;
else
head
=
new
;
new
->
next
=
NULL
;
new
->
prev
=
tail
;
tail
=
new
;
item
=
item
->
next
;
}
return
head
;
}
static
stringtable_t
*
translate_stringtable
(
po_file_t
po
,
stringtable_t
*
stt
,
language_t
*
lang
,
int
*
found
)
{
stringtable_t
*
new
,
*
head
=
NULL
,
*
tail
=
NULL
;
int
i
;
while
(
stt
)
{
new
=
xmalloc
(
sizeof
(
*
new
)
);
*
new
=
*
stt
;
new
->
lvc
.
language
=
lang
;
new
->
lvc
.
version
=
get_dup_version
(
lang
);
new
->
entries
=
xmalloc
(
new
->
nentries
*
sizeof
(
*
new
->
entries
)
);
memcpy
(
new
->
entries
,
stt
->
entries
,
new
->
nentries
*
sizeof
(
*
new
->
entries
)
);
for
(
i
=
0
;
i
<
stt
->
nentries
;
i
++
)
if
(
stt
->
entries
[
i
].
str
)
new
->
entries
[
i
].
str
=
translate_string
(
po
,
stt
->
entries
[
i
].
str
,
found
);
if
(
tail
)
tail
->
next
=
new
;
else
head
=
new
;
new
->
next
=
NULL
;
new
->
prev
=
tail
;
tail
=
new
;
stt
=
stt
->
next
;
}
return
head
;
}
static
void
translate_dialog
(
po_file_t
po
,
dialog_t
*
dlg
,
dialog_t
*
new
,
int
*
found
)
{
if
(
dlg
->
title
)
new
->
title
=
translate_string
(
po
,
dlg
->
title
,
found
);
if
(
dlg
->
font
)
{
new
->
font
=
xmalloc
(
sizeof
(
*
dlg
->
font
)
);
new
->
font
=
dlg
->
font
;
new
->
font
->
name
=
translate_string
(
po
,
dlg
->
font
->
name
,
found
);
}
new
->
controls
=
translate_controls
(
po
,
dlg
->
controls
,
found
);
}
static
void
translate_resources
(
po_file_t
po
,
language_t
*
lang
)
{
resource_t
*
res
;
for
(
res
=
resource_top
;
res
;
res
=
res
->
next
)
{
resource_t
*
new
=
NULL
;
int
found
=
0
;
if
(
!
is_english
(
res
->
lan
))
continue
;
switch
(
res
->
type
)
{
case
res_acc
:
/* FIXME */
break
;
case
res_dlg
:
new
=
dup_resource
(
res
,
lang
);
translate_dialog
(
po
,
res
->
res
.
dlg
,
new
->
res
.
dlg
,
&
found
);
break
;
case
res_men
:
new
=
dup_resource
(
res
,
lang
);
new
->
res
.
men
->
items
=
translate_items
(
po
,
res
->
res
.
men
->
items
,
&
found
);
break
;
case
res_stt
:
new
=
dup_resource
(
res
,
lang
);
new
->
res
.
stt
=
translate_stringtable
(
po
,
res
->
res
.
stt
,
lang
,
&
found
);
break
;
case
res_msg
:
/* FIXME */
break
;
default:
break
;
}
if
(
new
&&
found
)
{
if
(
new_tail
)
new_tail
->
next
=
new
;
else
new_top
=
new
;
new
->
prev
=
new_tail
;
new_tail
=
new
;
}
}
}
void
add_translations
(
const
char
*
po_dir
)
{
resource_t
*
res
;
po_file_t
po
;
char
buffer
[
256
];
char
*
p
,
*
tok
,
*
name
;
unsigned
int
i
;
FILE
*
f
;
/* first check if we have English resources to translate */
for
(
res
=
resource_top
;
res
;
res
=
res
->
next
)
if
(
is_english
(
res
->
lan
))
break
;
if
(
!
res
)
return
;
new_top
=
new_tail
=
NULL
;
name
=
strmake
(
"%s/LINGUAS"
,
po_dir
);
if
(
!
(
f
=
fopen
(
name
,
"r"
)))
return
;
free
(
name
);
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
f
))
{
if
((
p
=
strchr
(
buffer
,
'#'
)))
*
p
=
0
;
for
(
tok
=
strtok
(
buffer
,
"
\t\r\n
"
);
tok
;
tok
=
strtok
(
NULL
,
"
\t\r\n
"
))
{
for
(
i
=
0
;
i
<
sizeof
(
languages
)
/
sizeof
(
languages
[
0
]);
i
++
)
if
(
!
strcmp
(
tok
,
languages
[
i
].
name
))
break
;
if
(
i
==
sizeof
(
languages
)
/
sizeof
(
languages
[
0
]))
error
(
"unknown language '%s'
\n
"
,
tok
);
name
=
strmake
(
"%s/%s.po"
,
po_dir
,
tok
);
if
(
!
(
po
=
po_file_read
(
name
,
&
po_xerror_handler
)))
error
(
"cannot load po file for language '%s'
\n
"
,
tok
);
translate_resources
(
po
,
new_language
(
languages
[
i
].
id
,
languages
[
i
].
sub
)
);
po_file_free
(
po
);
free
(
name
);
}
}
fclose
(
f
);
/* prepend the translated resources to the global list */
if
(
new_tail
)
{
new_tail
->
next
=
resource_top
;
resource_top
->
prev
=
new_tail
;
resource_top
=
new_top
;
}
}
#else
/* HAVE_LIBGETTEXTPO */
#else
/* HAVE_LIBGETTEXTPO */
void
write_pot_file
(
const
char
*
outname
)
void
write_pot_file
(
const
char
*
outname
)
...
@@ -713,4 +977,8 @@ void write_po_files( const char *outname )
...
@@ -713,4 +977,8 @@ void write_po_files( const char *outname )
error
(
"PO files not supported in this wrc build
\n
"
);
error
(
"PO files not supported in this wrc build
\n
"
);
}
}
void
add_translations
(
const
char
*
po_dir
)
{
}
#endif
#endif
tools/wrc/wrc.c
View file @
d8c986e0
...
@@ -71,6 +71,7 @@ static const char usage[] =
...
@@ -71,6 +71,7 @@ static const char usage[] =
" -o, --output=FILE Output to file (default is infile.res)
\n
"
" -o, --output=FILE Output to file (default is infile.res)
\n
"
" -O, --output-format=FORMAT The output format (`po', `pot', `res', or `res16`)
\n
"
" -O, --output-format=FORMAT The output format (`po', `pot', `res', or `res16`)
\n
"
" --pedantic Enable pedantic warnings
\n
"
" --pedantic Enable pedantic warnings
\n
"
" --po-dir=DIR Directory containing po files for translations
\n
"
" --preprocessor Specifies the preprocessor to use, including arguments
\n
"
" --preprocessor Specifies the preprocessor to use, including arguments
\n
"
" -r Ignored for compatibility with rc
\n
"
" -r Ignored for compatibility with rc
\n
"
" -U, --undefine id Undefine preprocessor identifier id
\n
"
" -U, --undefine id Undefine preprocessor identifier id
\n
"
...
@@ -171,6 +172,7 @@ enum long_options_values
...
@@ -171,6 +172,7 @@ enum long_options_values
LONG_OPT_NOSTDINC
=
1
,
LONG_OPT_NOSTDINC
=
1
,
LONG_OPT_TMPFILE
,
LONG_OPT_TMPFILE
,
LONG_OPT_NOTMPFILE
,
LONG_OPT_NOTMPFILE
,
LONG_OPT_PO_DIR
,
LONG_OPT_PREPROCESSOR
,
LONG_OPT_PREPROCESSOR
,
LONG_OPT_VERSION
,
LONG_OPT_VERSION
,
LONG_OPT_DEBUG
,
LONG_OPT_DEBUG
,
...
@@ -195,6 +197,7 @@ static const struct option long_options[] = {
...
@@ -195,6 +197,7 @@ static const struct option long_options[] = {
{
"output"
,
1
,
NULL
,
'o'
},
{
"output"
,
1
,
NULL
,
'o'
},
{
"output-format"
,
1
,
NULL
,
'O'
},
{
"output-format"
,
1
,
NULL
,
'O'
},
{
"pedantic"
,
0
,
NULL
,
LONG_OPT_PEDANTIC
},
{
"pedantic"
,
0
,
NULL
,
LONG_OPT_PEDANTIC
},
{
"po-dir"
,
1
,
NULL
,
LONG_OPT_PO_DIR
},
{
"preprocessor"
,
1
,
NULL
,
LONG_OPT_PREPROCESSOR
},
{
"preprocessor"
,
1
,
NULL
,
LONG_OPT_PREPROCESSOR
},
{
"target"
,
1
,
NULL
,
'F'
},
{
"target"
,
1
,
NULL
,
'F'
},
{
"undefine"
,
1
,
NULL
,
'U'
},
{
"undefine"
,
1
,
NULL
,
'U'
},
...
@@ -334,6 +337,7 @@ int main(int argc,char *argv[])
...
@@ -334,6 +337,7 @@ int main(int argc,char *argv[])
int
i
;
int
i
;
int
cmdlen
;
int
cmdlen
;
int
po_mode
=
0
;
int
po_mode
=
0
;
char
*
po_dir
=
NULL
;
char
**
files
=
xmalloc
(
argc
*
sizeof
(
*
files
)
);
char
**
files
=
xmalloc
(
argc
*
sizeof
(
*
files
)
);
signal
(
SIGSEGV
,
segvhandler
);
signal
(
SIGSEGV
,
segvhandler
);
...
@@ -378,6 +382,9 @@ int main(int argc,char *argv[])
...
@@ -378,6 +382,9 @@ int main(int argc,char *argv[])
case
LONG_OPT_NOTMPFILE
:
case
LONG_OPT_NOTMPFILE
:
if
(
debuglevel
)
warning
(
"--no-use-temp-file option not yet supported, ignored.
\n
"
);
if
(
debuglevel
)
warning
(
"--no-use-temp-file option not yet supported, ignored.
\n
"
);
break
;
break
;
case
LONG_OPT_PO_DIR
:
po_dir
=
xstrdup
(
optarg
);
break
;
case
LONG_OPT_PREPROCESSOR
:
case
LONG_OPT_PREPROCESSOR
:
if
(
strcmp
(
optarg
,
"cat"
)
==
0
)
no_preprocess
=
1
;
if
(
strcmp
(
optarg
,
"cat"
)
==
0
)
no_preprocess
=
1
;
else
fprintf
(
stderr
,
"-P option not yet supported, ignored.
\n
"
);
else
fprintf
(
stderr
,
"-P option not yet supported, ignored.
\n
"
);
...
@@ -555,6 +562,7 @@ int main(int argc,char *argv[])
...
@@ -555,6 +562,7 @@ int main(int argc,char *argv[])
output_name
=
NULL
;
output_name
=
NULL
;
exit
(
0
);
exit
(
0
);
}
}
if
(
po_dir
)
add_translations
(
po_dir
);
/* Convert the internal lists to binary data */
/* Convert the internal lists to binary data */
resources2res
(
resource_top
);
resources2res
(
resource_top
);
...
...
tools/wrc/wrc.h
View file @
d8c986e0
...
@@ -58,6 +58,7 @@ extern language_t *currentlanguage;
...
@@ -58,6 +58,7 @@ extern language_t *currentlanguage;
void
verify_translations
(
resource_t
*
top
);
void
verify_translations
(
resource_t
*
top
);
void
write_pot_file
(
const
char
*
outname
);
void
write_pot_file
(
const
char
*
outname
);
void
write_po_files
(
const
char
*
outname
);
void
write_po_files
(
const
char
*
outname
);
void
add_translations
(
const
char
*
po_dir
);
void
write_resfile
(
char
*
outname
,
resource_t
*
top
);
void
write_resfile
(
char
*
outname
,
resource_t
*
top
);
static
inline
void
set_location
(
location_t
*
loc
)
static
inline
void
set_location
(
location_t
*
loc
)
...
...
tools/wrc/wrc.man.in
View file @
d8c986e0
...
@@ -107,6 +107,12 @@ input.
...
@@ -107,6 +107,12 @@ input.
Enable pedantic warnings. Notably redefinition of #define statements can
Enable pedantic warnings. Notably redefinition of #define statements can
be discovered with this option.
be discovered with this option.
.TP
.TP
.I \fB\-\-po-dir=\fIdir\fR
Enable the generation of resource translations based on po files
loaded from the specified directory. That directory must follow the
gettext convention, in particular in must contain one .po file for
each language, and a LINGUAS file listing the available languages.
.TP
.I \fB\-r\fR
.I \fB\-r\fR
Ignored for compatibility with \fIrc\fR.
Ignored for compatibility with \fIrc\fR.
.TP
.TP
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment