Skip to content

A flexible C++ formatting library designed for i18n, using embedded script to output plural forms, grammatical gender, etc. correctly

License

Notifications You must be signed in to change notification settings

HenryAWE/PapilioCharontis

Repository files navigation

Other language: 中文

🦋 Papilio Charontis

Build

A flexible C++ formatting library, mainly designed for internationalization (i18n) scenarios. It can also be used as a replacement for printf, <iostream> and std::format.

The output content can be controlled by embedded scripts. Output logics such as plural form or grammatical gender is detached from the program logic, leaving it completely under control of the translation.

For example, if you want to output correctly in the legacy way, the code may look like this:

if(n == 1)
    print(translate("Found {} file"), n);
else
    print(translate("Found {} files"), n);

This code will mix the output logic with other logic, and it cannot handle languages whose number of plural forms is not similar to English such as Russian.

With this library, the code can be rewritten as:

print(translate("Found {0} file{${0}!=1:'s'}"), n);

Overview

Main Feature: Embedded Script

You can use the embedded script to control the output, such as using plural form of a word for a certain number.

Example 1:

Based on the number of warnings, decide whether to use the plural form of the word "warning".

papilio::format("{0} warning{${0}>1:'s'}", 1); // Returns "1 warning"
papilio::format("{0} warning{${0}>1:'s'}", 2); // Returns "2 warnings"

Example 2:

Determine the form of words based on the number of items.

// English
std::string_view fmt_en =
    "There {${0}!=1: 'are' : 'is'} {0} apple{${0}!=1: 's'}";
papilio::format(fmt_en, 1); // Returns "There is 1 apple"
papilio::format(fmt_en, 2); // Returns "There are 2 apples"

// French
std::string_view fmt_fr =
    "Il y a {0} pomme{${0}>1:'s'}";
papilio::format(fmt_fr, 1); // Returns "Il y a 1 pomme"
papilio::format(fmt_fr, 2); // Returns "Il y a 2 pommes"

// Chinese (no plural form)
std::string_view fmt_zh =
    "有 {0} 个苹果";
papilio::format(fmt_zh, 1); // Returns "有 1 个苹果"
papilio::format(fmt_zh, 2); // Returns "有 2 个苹果"

More Examples

More examples can be found in example/ directory.

Compatibility with {fmt} and C++ 20 <format> in Usages

This library is consistent with {fmt} and <format> in basic formatting syntax.

// Format specifier
papilio::format("#{:08x}", 0xff);                  // Returns "#000000ff"
// Escaped sequences for outputting braces
papilio::format("{{plain text}}");                 // Returns "{plain text}"
// Relocating arguments
papilio::format("{1} and {0}", "second", "first"); // Returns "first and second"

See Built-In Formatter for more information about built-in format specifiers.

Named arguments from {fmt} are also supported.

using namespace papilio::literals;
papilio::format("{text} and {0}", "world", "text"_a = "hello");
// Returns "hello and world"

If you don't want using namespace, you can use papilio::arg("text", "hello") instead.

Additional Feature

Converting enum values to string without additional code.

enum animal
{
    cat = 1,
    dog
};

papilio::format("{}", cat);   // Returns "cat"
papilio::format("{}", dog);   // Returns "dog"
papilio::format("{:d}", cat); // Returns "1"

Accessing Member

Support accessing member attributes, and subscripting by integer, range, or string.

papilio::format("length of \"{0}\" is {0.length}", "hello");
// Returns "length of "hello" is 5"
papilio::format("{[:5]:}", "hello world");  // Returns "hello"
papilio::format("{[-5:]:}", "hello world"); // Returns "world"
papilio::format("{[0]:}", "hello world");   // Returns "h"
papilio::format("{[-1]:}", "hello world");  // Returns "d"

See Built-In Accessors for more information.

Unicode Support

You can conveniently operate Unicode strings in formatting function.

papilio::format("{[:2]}", "你好,世界");
// Returns "你好" instead of first two bytes which cannot represent a valid character
papilio::format("Length: {0.length}; Size: {0.size}", "你好,世界");
// Returns "Length: 5; Size: 15"

NOTE: In order to run the above code, you need to make sure your code is saved in UTF-8 encoding and the correct compiler flags is set (like /utf-8 of MSVC). You can use the u8 prefix to force the string to use UTF-8 encoding.

Formatting Support for wchar_t, char8_t, char16_t, and char32_t

papilio::format(L"{}", true);  // Returns L"true"
papilio::format(u8"{}", true); // Returns u8"true"
papilio::format(u"{}", true);  // Returns u"true"
papilio::format(U"{}", true);  // Returns U"true"

NOTE: Support for char8_t, char16_t, and char32_t added by newer C++ standard needs to include <papilio/xchar.hpp>.

C++ 20 Modules Support

import papilio;

int main()
{
    papilio::print("Hello world from imported module!");
}

NOTE: This feature requires you to compile the library with papilio_build_module set to ON. See Custom Build for more information.

Documentation

  1. Build: How to build the project.
  2. Frequently Asked Questions
  3. Examples
  4. Introduction to the Script
  5. Built-In Formatter: Built-in formatter for common types. You can find documents for format specification of those common types.
  6. Built-In Accessor: Built-in accessor for common types.
  7. Custom Formatter: Add format support for custom types in order to output them.
  8. Custom Accessor: Add indexing, slicing and attribute support for custom type.

License

MIT License

About

A flexible C++ formatting library designed for i18n, using embedded script to output plural forms, grammatical gender, etc. correctly

Topics

Resources

License

Stars

Watchers

Forks