Command or Option for The Xgettext, Msginit, Msgfmt Sequence for Setting The Mime Type

msgfmt invalid multibyte sequence error on a Polish text

Edit plt_polish.po and change the Content-Type line to "Content-Type: text/plain; charset=UTF-8\n" (Changing the charset from ASCII to UTF-8)

How to localize c++/cmake program using GNU gettext

how to generate .pot files

You write them by hand or generate with msginit. It's the same as .po, just a different name for documentation.

Could you provide an example of GNU gettext usage to localize the following program

The following:

cat >./CMakeLists.txt <<EOF
cmake_minimum_required(VERSION 3.11)
project(trans)
include(CTest)
add_executable(main main.cpp)
file(GLOB ffs "lang/*.po")
set(TEXTDOMAIN myprogram)
make_directory(${CMAKE_CURRENT_BINARY_DIR}/locale)
foreach(ff IN LISTS ffs)
get_filename_component(lang ${ff} NAME_WE)
make_directory(${CMAKE_CURRENT_BINARY_DIR}/locale/${lang})
make_directory(${CMAKE_CURRENT_BINARY_DIR}/locale/${lang}/LC_MESSAGES)
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/locale/${lang}/LC_MESSAGES/${TEXTDOMAIN}.mo
DEPENDS
${ff}
COMMAND msgfmt -o
${CMAKE_CURRENT_BINARY_DIR}/locale/${lang}/LC_MESSAGES/${TEXTDOMAIN}.mo
${ff}
)
add_custom_target(gen_${lang} ALL DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/locale/${lang}/LC_MESSAGES/${TEXTDOMAIN}.mo
)
add_test(NAME ${lang} COMMAND main)
set_property(TEST ${lang} APPEND PROPERTY ENVIRONMENT
TEXTDOMAINDIR=${CMAKE_CURRENT_BINARY_DIR}/locale
LANGUAGE=${lang}
)
set_tests_properties(${lang} PROPERTIES
PASS_REGULAR_EXPRESSION "${lang} foo"
)
endforeach()
EOF

cat >./main.cpp <<EOF
#include <iostream>
#include <string>
#include <libintl.h>
#include <cstdlib>
#include <clocale>
int main() {
setlocale(LC_ALL, "");
const char *textdomainstr = "myprogram";
const char *textdomaindir = getenv("TEXTDOMAINDIR");
if (textdomaindir) {
bindtextdomain(textdomainstr, textdomaindir);
}
textdomain(textdomainstr);
//
std::string name = "foo";
std::cout << gettext(name.c_str()) << "\n";
}
EOF

cat >./lang/de_DE.po <<EOF
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"

msgid "foo"
msgstr "de_DE foo"

EOF

cat >./lang/en_US.po <<EOF
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"

msgid "foo"
msgstr "en_US foo"

EOF

cat >./lang/pl_PL.po <<EOF
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"Language: pl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"

msgid "foo"
msgstr "pl_PL foo"

EOF

Results in:

+ cmake -H. -B./_build --no-warn-unused-cli -DCMAKE_VERBOSE_MAKEFILE=1 -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_C_FLAGS=-Wall -ggdb3 -Wno-unused-function -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -DCMAKE_CXX_FLAGS=-Wall -ggdb3 -Wno-unused-function -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=bin -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=lib -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=lib -G Ninja
Not searching for unused variables given on the command line.
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /dev/shm/.1000.home.tmp.dir/_build
+ cmake --build ./_build --parallel --verbose
[1/5] cd /dev/shm/.1000.home.tmp.dir/_build && msgfmt -o /dev/shm/.1000.home.tmp.dir/_build/locale/de_DE/LC_MESSAGES/myprogram.mo /dev/shm/.1000.home.tmp.dir/lang/de_DE.po
[2/5] cd /dev/shm/.1000.home.tmp.dir/_build && msgfmt -o /dev/shm/.1000.home.tmp.dir/_build/locale/en_US/LC_MESSAGES/myprogram.mo /dev/shm/.1000.home.tmp.dir/lang/en_US.po
[3/5] cd /dev/shm/.1000.home.tmp.dir/_build && msgfmt -o /dev/shm/.1000.home.tmp.dir/_build/locale/pl_PL/LC_MESSAGES/myprogram.mo /dev/shm/.1000.home.tmp.dir/lang/pl_PL.po
[4/5] /usr/bin/c++ -Wall -ggdb3 -Wno-unused-function -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /dev/shm/.1000.home.tmp.dir/main.cpp
[5/5] : && /usr/bin/c++ -Wall -ggdb3 -Wno-unused-function -fsanitize=address -fsanitize=undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract CMakeFiles/main.dir/main.cpp.o -o bin/main && :
+ cd ./_build && ctest -V
UpdateCTestConfiguration from :/dev/shm/.1000.home.tmp.dir/_build/DartConfiguration.tcl
Parse Config file:/dev/shm/.1000.home.tmp.dir/_build/DartConfiguration.tcl
UpdateCTestConfiguration from :/dev/shm/.1000.home.tmp.dir/_build/DartConfiguration.tcl
Parse Config file:/dev/shm/.1000.home.tmp.dir/_build/DartConfiguration.tcl
Test project /dev/shm/.1000.home.tmp.dir/_build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
Start 1: de_DE

1: Test command: /dev/shm/.1000.home.tmp.dir/_build/bin/main
1: Working Directory: /dev/shm/.1000.home.tmp.dir/_build
1: Environment variables:
1: TEXTDOMAINDIR=/dev/shm/.1000.home.tmp.dir/_build/locale
1: LANGUAGE=de_DE
1: Test timeout computed to be: 1500
1: de_DE foo
1/3 Test #1: de_DE ............................ Passed 0.01 sec
test 2
Start 2: en_US

2: Test command: /dev/shm/.1000.home.tmp.dir/_build/bin/main
2: Working Directory: /dev/shm/.1000.home.tmp.dir/_build
2: Environment variables:
2: TEXTDOMAINDIR=/dev/shm/.1000.home.tmp.dir/_build/locale
2: LANGUAGE=en_US
2: Test timeout computed to be: 1500
2: en_US foo
2/3 Test #2: en_US ............................ Passed 0.01 sec
test 3
Start 3: pl_PL

3: Test command: /dev/shm/.1000.home.tmp.dir/_build/bin/main
3: Working Directory: /dev/shm/.1000.home.tmp.dir/_build
3: Environment variables:
3: TEXTDOMAINDIR=/dev/shm/.1000.home.tmp.dir/_build/locale
3: LANGUAGE=pl_PL
3: Test timeout computed to be: 1500
3: pl_PL foo
3/3 Test #3: pl_PL ............................ Passed 0.01 sec

100% tests passed, 0 tests failed out of 3

Total Test time (real) = 0.04 sec

how to generate .pot files with the given project structure

I always understood that .pot files are .po files. They are the same. You write them, or let msginit generate them from a template file, where this template file was also written by you, or generated by some script. I understood it's a hint in documentation like msgmerge that those are different files, like .pot has only one translation and msgmerge updates it in .po file.

You have to generate .mo files in proper <lang>/LC_MESSAGES/<textdomain>.mo directory and name structure.

Should a function have only one return statement?

I often have several statements at the start of a method to return for "easy" situations. For example, this:

public void DoStuff(Foo foo)
{
if (foo != null)
{
...
}
}

... can be made more readable (IMHO) like this:

public void DoStuff(Foo foo)
{
if (foo == null) return;

...
}

So yes, I think it's fine to have multiple "exit points" from a function/method.



Related Topics



Leave a reply



Submit