A strictly typed, lightweight internationalization and localization system for multilingual programs.
- Dictionaries are written in code, and the presence and correctness of translations are checked by the compiler
- Built-in support for string formatting based on std::format
- Static verification of the required number of substitutions in the translated strings
- Clean code without singletons and other magic
- Support for dynamic translation switching. This can be useful, for example, in HTTP request handlers
- Support for lazy translation. This allows you to generate a translatable string once, and then, for example, translate it into the system language in the error handler during logging, and return it in the request language in the server response.
- A library with a single header makes it easy to add translations to your project
- C++20
- No dependencies requires
#include <i18n_strict.h>
struct test_dict : public i18n_strict::dict {
str<> app_started;
str<int, std::string> transfer_money_to_account;
};
test_dict create_en_test_dict()
{
return {
.app_started { "Application started" },
.transfer_money_to_account { "Transfer {} to account {}" },
};
}
test_dict create_ru_test_dict()
{
return {
.app_started { "Приложение запущено" },
.transfer_money_to_account { "Перевести {} на счет {}" },
};
}
auto tr = i18n_strict::create_text_translator<test_dict>("ru",
{
{ "en", create_en_test_dict() },
{ "ru", create_ru_test_dict() },
});
TEST_CASE("Translation")
{
auto tr = i18n_strict::create_text_translator<test_dict>("ru",
{
{ "en", create_en_test_dict() },
{ "ru", create_ru_test_dict() },
});
SECTION("Translate simple text to english")
{
REQUIRE(tr->translate("en", &test_dict::app_started) == "Application started");
}
SECTION("Translate simple text to default language")
{
REQUIRE(tr->translate(&test_dict::app_started) == "Приложение запущено");
}
SECTION("Translate formatted message to english")
{
REQUIRE(tr->translate("en", &test_dict::transfer_money_to_account, 10, std::string("John"))
== "Transfer 10 to account John");
}
SECTION("Use translatable string to translate later")
{
i18n_strict::tr_str str(tr, &test_dict::transfer_money_to_account, 10, "John");
REQUIRE(str.translate("en") == "Transfer 10 to account John");
REQUIRE(str.translate() == "Перевести 10 на счет John");
}
}Just copy and include lib/i18n_strict.h in your project.
Add to your cmake project:
# Use C++20
set(CMAKE_CXX_STANDARD 20)
# Include i18n::strict
include(FetchContent)
FetchContent_Declare(
i18n_strict
GIT_REPOSITORY https://github.com/navrocky/i18n-strict.git
GIT_TAG 1.0.0 # Place the needed version here
OVERRIDE_FIND_PACKAGE
)
set(BUILD_TESTS OFF CACHE BOOL "Disable tests" FORCE)
FetchContent_MakeAvailable(i18n_strict)
include_directories(${i18n_strict_SOURCE_DIR}/lib)After then include library as usual:
#include <i18n_strict.h>
- Run unit tests with Github Actions
- Improve inline documentation
- Generate documentation with Doxygen
- Describe installation with CMake FetchContent
- Add package to vcpkg
- Add package to Conan Center