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
Cuda - Confusion About The Visual Profiler Results of "Branch" and "Divergent Branch" (2)
Ssl/Qsslsocket_Openssl.Cpp:1414: Error: Q_Ssl_Ctrl Was Not Declared in This Scope Error
Linux Shell Script - Find All Files and Run a Command on Each One of Them
Generic Printing Using a Usb Port
Implementation of Function Execve (Unistd.H)
Vue Npm Run Serve Failed to Load Resource: Net::Err_Content_Length_Mismatch
Counting Lines Starting with a Certain Word
Linux Shell Scripting: How to Remove Final Numbers in a Word List File
Range: Bytes 0- Fails in Apache 2.2.23
Git Status Between Windows and Linux Does Not Agree
Linux Sysfs Gpio: What Re-Arms Interrupt
Linking with 32Bit Libraries Under Linux 64Bit
How to Ensure Data Reaches Storage, Bypassing Memory/Cache/Buffered-Io
Why 2 Linux Processes of Same File Cannot Share Text Segment
How to Boot with My Latest Rpi-3.18.0 Kernel and Enabling The Device Tree